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秒
    强制唤醒
    主程序结束
  • 相关阅读:
    poj 3280 Cheapest Palindrome(区间DP)
    POJ 2392 Space Elevator(多重背包)
    HDU 1285 定比赛名次(拓扑排序)
    HDU 2680 Choose the best route(最短路)
    hdu 2899 Strange fuction (三分)
    HDU 4540 威威猫系列故事――打地鼠(DP)
    HDU 3485 Count 101(递推)
    POJ 1315 Don't Get Rooked(dfs)
    脱离eclipse,手动写一个servlet
    解析xml,几种方式
  • 原文地址:https://www.cnblogs.com/perfei/p/11529122.html
Copyright © 2011-2022 走看看