• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

3.1gocontext代码示例

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
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秒
强制唤醒
主程序结束

 

golang context包  WithValue

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
[MRCTF2020]hello_world_go发布时间:2022-07-10
下一篇:
[Go] 开发 go web 项目,踩到的一些“坑”发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap