golang开发 深入理解 context
context的历史
context包在Go 1.7版本正式加入Go标准库。在加入之前我们看看Go团队核心成员Sameer Ajmani在2014年发表的一篇关于context介绍博客,地址:https://go.dev/blog/context 下面是介绍的翻译。
在Go服务器中,每个传入的请求都在自己的goroutine中处理。请求处理程序经常启动额外的goroutine来访问后端,如数据库和RPC服务。处理请求的goroutine集合通常需要访问特定于请求的值,例如最终用户的身份、授权令牌和请求的截止日期。当一个请求被取消或超时时,所有处理该请求的goroutine都应该迅速退出,这样系统就可以回收它们正在使用的任何资源。
在Google,我们开发了一个 context 包,可以轻松地将请求范围内的值、取消信号和截止日期跨API边界传递给处理请求所涉及的所有goroutine。该软件包作为上下文公开提供。
可以看到介绍里面主要说的是,应用中怎么控制大量的goroutine退出释放资源、请求范围内怎么传值,也就是说,context的引入主要是为了解决这两个问题。
context的基本使用
context初始化的方法有五个,一个是main goroutine 初始化,一个主要是是用来传值的,经常使用的就三个。
未超时的时候,执行取消,依赖取消函数
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "main", "main-value")
ctx1,cancel := context.WithDeadline(ctx, time.Now().Add(3*time.Second))
go cancelFunc(ctx1)
//取消函数
cancel()
time.Sleep(time.Duration(5*time.Second))
}
执行结果
main-param main-value
退出协程
超时的时候执行结果,超过三秒的超时时间,依赖超时时间
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "main", "main-value")
ctx1,_ := context.WithDeadline(ctx, time.Now().Add(3*time.Second))
go cancelFunc(ctx1)
time.Sleep(time.Duration(5*time.Second))
}
执行结果
main-param main-value
1秒
1秒
1秒
退出协程
看注释和执行流程,基本能理解,main函数调用cancel就能取消正在执行的goroutine协程。WithDeadline和WithTimeout 除过可以通过调用取消函数,还可以通过设置超时时间点和时间段取消goroutine的执行。
context如何控制多个goroutine,如何传值给多个goroutine
看图示,root context控制着所有的goroutine,context1控制着 goroutine2 goroutine3 goroutine4 goroutine5 goroutine6 goroutine7,context2 控制着goroutine4 goroutine5,context3 控制着goroutine6 goroutine7。
使用图示的goroutine 编写测试代码
package main
import (
"context"
"fmt"
"time"
)
func func1(ctx context.Context) {
fmt.Println("func1-main-param", ctx.Value("main"))
ctx1 := context.WithValue(ctx, "func1-param", "func1-value")
go func2(ctx1)
select {
case <-ctx1.Done():
fmt.Println("goroutine 1 exit")
}
}
func func2(ctx context.Context) {
fmt.Println("func2-main-param", ctx.Value("main"))
fmt.Println("func2-func1-param", ctx.Value("func1-param"))
ctx2, _ := context.WithCancel(ctx)
go func4(ctx2)
go func5(ctx2)
select {
case <-ctx2.Done():
fmt.Println("goroutine 2 exit")
}
}
func func4(ctx context.Context) {
select {
case <-ctx.Done():
fmt.Println("goroutine 4 exit")
}
}
func func5(ctx context.Context) {
select {
case <-ctx.Done():
fmt.Println("goroutine 5 exit")
}
}
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "main", "main-value")
ctx,cancel := context.WithCancel(ctx)
go func1(ctx)
cancel()
time.Sleep(time.Duration(5*time.Second))
}
运行结果
func1-main-param main-value
goroutine 1 exit
func2-main-param main-value
func2-func1-param func1-value
goroutine 2 exit
goroutine 5 exit
goroutine 4 exit
可以看到最终实现结果和场景,跟Sameer Ajmani在博客描述的是一样的,context的出现主要两个作用,控制 goroutine,goroutine之间传值。
golang开发 深入理解 context的更多相关文章
- 全面理解Context
出处:http://blog.csdn.net/lmj623565791/article/details/40481055,本文出自:[张鸿洋的博客] 本文大多数内容翻译自:http://www.do ...
- grpc(3):使用 golang 开发 grpc 服务端和client
1,关于grpc-go golang 能够能够做grpc的服务端和client. 官网的文档: http://www.grpc.io/docs/quickstart/go.html https://g ...
- go笔记--几个例子理解context的作用
目录 go笔记--几个例子理解context的作用 context interface 先看一个简单的例程 context的作用 contxt相关函数 go笔记--几个例子理解context的作用 经 ...
- 十分钟学会Golang开发gRPC服务
gRPC是Google发起的一个开源RPC框架,使用HTTP/2传输协议,使用Protocol Buffers编码协议,相比RESTful框架的程序性能提高不少,而且当前流行的编程语言基本都已经支持. ...
- 用golang开发系统软件的一些细节
用golang开发系统软件的一些细节 作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 (本文的pdf版本) ...
- 使用golang 开发的 andriod应用
最近在捣鼓一个东东,就是使用golang开发andriod应用.说起来简单操作起来还挺麻烦,中间又学习了很多东西.比如ubuntu,docker,angular,ionic,jquery mobile ...
- golang开发android环境搭建_window
golang开发android环境搭建介绍 一 安装依赖软件: git:版本管理 go: go开发环境(版本>=1.5),可直接下载window版的go安装包. android studio: ...
- Android-5 理解context
context -- 用来访问全局信息 Application用途 Application生命周期 深入理解 Context http://blog.csdn.net/z1074971432/arti ...
- Windows下visual studio code搭建golang开发环境
Windows下visual studio code搭建golang开发环境 序幕 其实环境搭建没什么难的,但是遇到一些问题,主要是有些网站资源访问不了(如:golang.org),导致一些包无法安装 ...
- go get报错unrecognized import path “golang.org/x/net/context”…
今天安装gin框架,首先下载gin,命令如下:go get github.com/mattn/go-sqlite3 结果报错: package golang.org/x/net/context: un ...
随机推荐
- git 常见命令和资源
git练习 常用git清单 强制切换分支所指位置 git branch -f main c3强制分支main指向c3 git branch -f main HEAD~3强制分支main指向head的父 ...
- golang开发:环境篇(三)开发利器Goland安装
这节主要介绍下golang开发的最主要的IDE,Goland.可以有效提高开发效率.用过一段时间 IntelliJ+GO插件,其实功能上跟goland差不多.不过团队的其它开发者基本都是Goland, ...
- 本地锁 & 分布式锁
引子: 解决缓存击穿问题 synchronized (this){代码块} public synchronized Map<String,List<Catelog2Vo>> g ...
- Rust GUI库 egui 的简单应用
目录 简介 简单示例 创建项目 界面设计 切换主题 自定义字体 自定义图标 经典布局 定义导航变量 实现导航界面 实现导航逻辑 实现主框架布局 调试运行 参考资料 简介 egui(发音为"e ...
- WPF之事件
目录 WPF的树形结构 事件 路由事件 使用WPF内置路由事件 自定义路由事件 ButtonBase类的Click路由事件 创建一个路由事件 RoutedEventArgs的Source与Origin ...
- KETTLE实战视频教程--免费白嫖(本贴持续更新)
KETTLE实战视频教程 欢迎关注笔者的公众号: java大师, 每日推送java.kettle运维等领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!!个人网站: http://w ...
- Markdown 使用diff高亮代码区某行数据
使用diff标明代码区即可 如: ```diff fun main(){ + say("") return "" } fun main(){ - say(&qu ...
- 使用正则表达式提取background:url()中的内容
开发中经常碰见元素使用background或者background-imgae等样式表提供的属性来展示图片而不是img使用标签,在修改的时候就会发现弊端在需要动态修改图片的时候没有img.src那样顺 ...
- 记录--使用Canvas绘制一个验证码组件
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 使用Canvas绘制一个验证码组件 前言 验证码,这一日常伴随我们的要素,是我们在线交互的重要安全保障.你的手机短信里是否被它占据半壁江山 ...
- 浅谈 KingbaseES 和 SQLServer 中的 instead of 触发器
本文基于Kingbase和SqlServer的INSTEAD OF 触发器主要功能特点进行对比浅析,同时针对SqlServer 的INSTEAD OF 触发器提出了多种kingbase环境的等价代码方 ...