Go语言的协程上下文的几个方法和用法


Posted in Golang onApril 11, 2022

go协程上下文context

golang的context 主要用来在 goroutine 之间传递上下文信息,包括:取消信号、超时时间、截止时间、k-v 等

context是golang1.17版本之后才出的特性

上下文解决的问题

  • 协程间的通信

例如web应用中,每一个请求都由一个协程去处理。当然处理处理请求的这个协程,一般我们还会起一些其他的协程,用来处理其他的业务,比如操作数据库,生份验证、文件读写等。这些协程是独立的,我们在当前的协程中无法感知到其他的协程执行的情况怎么样了。实用通道channel可以实现通讯功能

contextcontext.WithValue()本质上也是通过channel来实现通讯

  • 子协程的超时处理

同样例如web应用当中,我们主进程是一直常驻内存的。每一个请求都由一个协程去处理,在处理业务的过程中可能会起另外的协程去处理其他的业务,当子协程出现了异常或者阻塞了,无法向上一级的协程反馈信息,主协程接受不到反馈也会阻塞。上下文可以很好的解决这个问题,context可以实现子协程或子孙协程的超时退出或定时退出

上下文的几个方法和用法

context.WithCancel(context.Context)

WithCancel()方法传入一个上下文空实例,直接用context.Background()即可,返回一个上下文和一个取消函数。调用cancal()会向其他协程传递信号,收到信号后子协程就可以做关闭或其他处理

package main
​
import (
    "context"
    "fmt"
    "time"
)
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
func main() {
    ctx, cancal := context.WithCancel(context.Background())
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}

context.WithTimeout(context.Context,timeout)

定义一个会超时的上下文,实例化后倒计时就开始,到时间会自动调用cancel()函数通知子协程,也可以手动调用cancel()通知。如果子协程中还有子协程,继续使用这个上下文,当主协程发出取消信号时每一个使用了这个上下文的都会收到通知

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithTimeout(context.Background(), time.Second*2)
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}

context.WithDeadline(context.Context,(绝对时间)timeout)

定义一个会超时的上下文,与Timeout不同在于,传入的时间是一个绝对时间。到了指定的时间会自动调用cancel()函数通知子协程,也可以手动调用cancel()通知。如果子协程中还有子协程,继续使用这个上下文,当主协程发出取消信号时每一个使用了这个上下文的都会收到通知

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithDeadline(context.Background(), time.Now().Add(3 * time.Second))
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}

协程间的上下文通讯:context.WithValue()

先看一下这段代码

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
type CTXKEY string
​
func worker(ctx context.Context) {
    // 在子协程中获取上下文信息
    num, ok := ctx.Value(CTXKEY("num")).(string)
    if !ok {
        fmt.Println("invalid trace code")
    }
    fmt.Println(num)
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithDeadline(context.Background(), time.Now().Add(3*time.Second))
    // 利用上下文传一个 num = 1234567
    // 实例化一个上下文
    ctx = context.WithValue(ctx, CTXKEY("num"), "1234567")
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
}

通过上下文实现协程间的通信,如果项目大,为了避免变量的污染,原则上:上下文通信所用的key需要自定义一个类型

type traceCode string;context.WithValue(context.Context,key,value)

到此这篇关于golang的协程上下文的文章就介绍到这了,更多相关golang的协程上下文内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Golang 相关文章推荐
Golang二维切片初始化的实现
Apr 08 Golang
golang正则之命名分组方式
Apr 25 Golang
golang中实现给gif、png、jpeg图片添加文字水印
Apr 26 Golang
golang在GRPC中设置client的超时时间
Apr 27 Golang
golang 如何通过反射创建新对象
Apr 28 Golang
基于Go Int转string几种方式性能测试
Apr 28 Golang
goland 设置project gopath的操作
May 06 Golang
golang实现一个简单的websocket聊天室功能
Oct 05 Golang
golang语言指针操作
Apr 14 Golang
golang用type-switch判断interface的实际存储类型
Apr 14 Golang
Golang 链表的学习和使用
Apr 19 Golang
Go Grpc Gateway兼容HTTP协议文档自动生成网关
Jun 16 Golang
Golang 1.18 多模块Multi-Module工作区模式的新特性
Apr 11 #Golang
golang三种设计模式之简单工厂、方法工厂和抽象工厂
Golang原生rpc(rpc服务端源码解读)
Apr 07 #Golang
Go并发4种方法简明讲解
Go归并排序算法的实现方法
Apr 06 #Golang
golang操作rocketmq的示例代码
Apr 06 #Golang
victoriaMetrics库布隆过滤器初始化及使用详解
You might like
PHP获取类中常量,属性,及方法列表的方法
2009/04/09 PHP
从手册去理解分析PHP session机制
2011/07/17 PHP
PHP实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
Laravel框架FormRequest中重写错误处理的方法
2019/02/18 PHP
判断多个元素(RADIO,CHECKBOX等)是否被选择的原理说明
2009/02/18 Javascript
javascript 无提示关闭窗口脚本
2009/08/17 Javascript
js修改table中Td的值(定义td的双击事件)
2013/01/10 Javascript
jquery.validate的使用说明介绍
2013/11/12 Javascript
vue中渐进过渡效果实现
2016/10/27 Javascript
domReady的实现案例
2016/11/23 Javascript
详解微信小程序 登录获取unionid
2017/06/27 Javascript
node.js基础知识小结
2018/02/26 Javascript
vue中使用cookies和crypto-js实现记住密码和加密的方法
2018/10/18 Javascript
详解基于iview-ui的导航栏路径(面包屑)配置
2019/02/22 Javascript
微信小程序实现Swiper轮播图效果
2019/11/22 Javascript
Antd表格滚动 宽度自适应 不换行的实例
2020/10/27 Javascript
[50:27]Secret vs VG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
Python通过解析网页实现看报程序的方法
2014/08/04 Python
python使用线程封装的一个简单定时器类实例
2015/05/16 Python
python安装virtualenv虚拟环境步骤图文详解
2019/09/18 Python
keras model.fit 解决validation_spilt=num 的问题
2020/06/19 Python
python获取本周、上周、本月、上月及本季的时间代码实例
2020/09/08 Python
应用心理学个人求职信范文
2013/12/11 职场文书
关于工资低的辞职信
2014/01/14 职场文书
大型车展策划方案
2014/02/01 职场文书
行政助理的岗位职责
2014/02/18 职场文书
班组长岗位职责
2014/03/03 职场文书
体育专业自荐书
2014/05/29 职场文书
教师工作失职检讨书
2014/09/18 职场文书
工作失误检讨书(3篇)
2014/10/11 职场文书
道德模范事迹材料
2014/12/20 职场文书
人事局接收函
2015/01/30 职场文书
考勤制度通知
2015/04/25 职场文书
2015年七夕情人节感言
2015/08/03 职场文书
Python预测分词的实现
2021/06/18 Python
Python用tkinter实现自定义记事本的方法详解
2022/03/31 Python