zoukankan      html  css  js  c++  java
  • 3.1 go context代码示例

    context.WithCancel
    返回两个有关联的对象,ctx与cancel,调用cancel发送一个空struct给ctx,ctx一旦接收到该对象后,就终止goroutine的执行;
    ctx是线程安全的,可以同时传递给多个goroutine,触发cancel时,取消所有goroutine的执行
    package main
    
    import (
        "context"
        "fmt"
        "time"
    )
    
    func testContext(){
        ctx,cancel := context.WithCancel(context.Background())
        go d1(ctx)
        go d2(ctx)
        
        time.Sleep(7*time.Second)
        cancel()
    }
    
    func d1(ctx context.Context){
        i:=0
        for {
            time.Sleep(1*time.Second)
            i++
            select {
                case <- ctx.Done():
                    fmt.Println("d1 over")
                    return
                    
                default:
                    fmt.Println("d1 ",i)
            }
        }
    }
    
    func d2(ctx context.Context){
    
        fmt.Println("d2 start")
        <- ctx.Done()
        fmt.Println("d2 over")
    }
    
    func main(){
        testContext()
        fmt.Println("main over")
    }

    输出

    d2 start
    d1  1
    d1  2
    d1  3
    d1  4
    d1  5
    d1  6
    main over
    context适用于这样的情况,你需要持续处理请求,有多个case分支,case分支中持续处理着数据,
    select 之前的代码不会被终止,下面的这种写法,会终止return之后的代码、以及其他case分支的代码
    case <- ctx.Done():
         fmt.Println("d1 over")
         return

    使用场景举例
    package main
    
    import (
        "context"
        "fmt"
        "time"
    )
    
    func d1(i *int)  chan int{
        var cc = make(chan int)
        go func() {
            for {
                time.Sleep(1*time.Second)
                *i = *i + 1
                cc <- *i
            }
        }()
        return cc
    }
    
    func textContext(cc chan int,ctx context.Context)  {
        for {
            select {
            case <- ctx.Done():
                fmt.Println("context done ")
                return
            case n:= <- cc :
                fmt.Println(n)
            }
        }
        fmt.Println("wg done")
    }
    
    func main() {
        ctx,cancel := context.WithCancel(context.Background())
    
    
        i:= 0
        var cc = d1(&i)
    
        go textContext(cc,ctx)
    
        for {
            time.Sleep(1*time.Second)
            if i > 10 {
                cancel()
                break
            }
        }
    }


     

    context.WithTimeout

    package main
    
    import (
        "fmt"
        "context"
        "time"
    )
    
    func d1(ctx context.Context){
        i := 0
        for{
            time.Sleep(1*time.Second)
            select{
                case <- ctx.Done():
                    fmt.Println("d1 over")
                    return
                default:
                    fmt.Println("d1:",i)
            }
        }
    }
    
    func test(){
        ctx,cancel := context.WithTimeout(context.Background(),5*time.Second)
        go d1(ctx)
        fmt.Println("begin sleep 10 sec")
        time.Sleep(10*time.Second)
        fmt.Println("10 sec over")
        cancel()
    }
    
    
    func main(){
        test()
    }
    
    [root@phoenix go]# go run cc.go 
    begin sleep 10 sec
    d1: 0
    d1: 0
    d1: 0
    d1: 0
    d1 over
    10 sec over
    

      

    无法中止正在执行中case分支

    package main
    
    import (
        "context"
        "fmt"
        "time"
    )
    
    func main() {
        ctx,cancel:= context.WithTimeout(context.Background(),5*time.Second)
        go timeOut(ctx)
    
        time.Sleep(10*time.Second)
        fmt.Println("强制唤醒")
        cancel()
        time.Sleep(5*time.Second)
        fmt.Println("主程序结束")
    }
    
    func timeOut(ctx context.Context)  {
    
        for{
            select {
            case <- ctx.Done():
                fmt.Println("context done")
    
            default:
                fmt.Println("沉睡100秒")
                time.Sleep(100*time.Second)
    
            }
        }
    }

    沉睡100秒这个case分支一旦开始执行,除非main协程结束,否则context是无法中止其执行的;5秒超时context发送了结束信号,但select有case未执行完,其channel处于阻塞状态,所以无法中止程序

    沉睡100秒
    强制唤醒
    主程序结束
  • 相关阅读:
    The Water Problem HDU-5443
    约瑟夫环1
    迪杰斯特拉算法1 HDU-1874
    [20200729NOIP提高组模拟T2]学数数——坎坷
    [20200728NOIP提高组模拟T4]有趣的有趣的家庭菜园——自闭了
    [20200728NOIP提高组模拟T1]Copy
    [20200728NOIP提高组模拟T2]愉快的logo设计
    [20200727NOIP提高组模拟T3]计算几何
    [20200727NOIP提高组模拟T2]走路
    [CQOI2015]任务查询系统
  • 原文地址:https://www.cnblogs.com/perfei/p/11529122.html
Copyright © 2011-2022 走看看