context使用
1. 概述
go语言中goroutine之间的关联关系,缺乏维护,在erlang中有专门的机制来保障新开协程的生命周期,在go语言中,只能通过channel + select来实现,但不够直观,很绕。
Context 通常被译作 上下文 ,它是一个比较抽象的概念,一般理解为程序单元的一个运行状态、现场、快照。上下上下则是存在上下层的传递, 上 会把内容传递给 下 。
在Go语言中,程序单元也就指的是Goroutine。context 包不仅实现了在程序单元之间共享状态变量的方法,同时能通过简单的方法,使我们在被调用程序单元的外部,通过设置ctx变量值,将过期或撤销信号传递给被调用的程序单元。
在go服务器中(http服务器),对于每个请求的request都是在单独的goroutine中进行的,处理一个request也可能涉及多个goroutine之间的交互, 使用context可以使开发者方便地在这些goroutine里传递request相关的数据、取消goroutine的signal或截止时间
Done 方法在Context被取消或超时时返回一个close的channel,close的channel可以作为广播通知,告诉给context相关的函数要停止当前工作然后返回。
当一个父operation启动一个goroutine用于子operation,这些子operation不能够取消父operation。下面描述的WithCancel函数提供一种方式可以取消新创建的Context.
Context可以安全的被多个goroutine使用。开发者可以把一个Context传递给任意多个goroutine然后cancel这个context的时候就能够通知到所有的goroutine。
Err方法返回context为什么被取消。
Deadline返回context何时会超时。
Value返回context相关的数据。
需要注意的就是 调用CancelFunc会取消child以及child生成的context,取出父context对这个child的引用,停止相关的计数器
实战:
- context.Background 只应用在最高等级,作为所有派生 context 的根。
- context.TODO 应用在不确定要使用什么的地方,或者当前函数以后会更新以便使用 context。
- context 取消是建议性的,这些函数可能需要一些时间来清理和退出。
- context.Value 应该很少使用,它不应该被用来传递可选参数。这使得 API 隐式的并且可以引起错误。取而代之的是,这些值应该作为参数传递。
- 不要将 context 存储在结构中,要在函数中显式传递它们,最好是作为第一个参数。
- 永远不要传递不存在的 context 。相反,如果您不确定使用什么,使用一个 ToDo context。
- Context 结构没有取消方法,因为只有派生 context 的函数才可以取消 context。
参考示例1:
package main import (
"context"
"log"
"os"
"time"
) var logg *log.Logger func someHandler() {
ctx, cancel := context.WithCancel(context.Background())
go doStuff(ctx) //10秒后取消doStuff
time.Sleep(10 * time.Second)
cancel() } //每1秒work一下,同时会判断ctx是否被取消了,如果是就退出
func doStuff(ctx context.Context) {
for {
time.Sleep(1 * time.Second)
select {
case <-ctx.Done():
logg.Printf("done")
return
default:
logg.Printf("work")
}
}
} func main() {
logg = log.New(os.Stdout, "", log.Ltime)
someHandler()
logg.Printf("down")
time.Sleep(10 * time.Second)
}
输出
18:00:17 work
18:00:18 work
18:00:19 work
18:00:20 work
18:00:21 work
18:00:22 work
18:00:23 work
18:00:24 work
18:00:25 work
18:00:26 down
18:00:26 done
参考示例2:
package main import (
"context"
"log"
"os"
"time"
) var logg *log.Logger func doTimeOutStuff(ctx context.Context) {
for {
time.Sleep(1 * time.Second) if deadline, ok := ctx.Deadline(); ok { //设置了deadl
logg.Printf("deadline set")
if time.Now().After(deadline) {
logg.Printf(ctx.Err().Error())
return
} } select {
case <-ctx.Done():
logg.Printf("done")
return
default:
logg.Printf("work")
}
}
} func timeoutHandler() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
// ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
go doTimeOutStuff(ctx)
// go doStuff(ctx) time.Sleep(10 * time.Second) cancel() } func main() {
logg = log.New(os.Stdout, "", log.Ltime)
timeoutHandler()
logg.Printf("down")
time.Sleep(10 * time.Second)
}
输出:
18:04:37 deadline set
18:04:37 work
18:04:38 deadline set
18:04:38 work
18:04:39 deadline set
18:04:39 work
18:04:40 deadline set
18:04:40 work
18:04:41 deadline set
18:04:41 context deadline exceeded
18:04:46 down
参考链接:
https://studygolang.com/articles/12566
https://www.cnblogs.com/zhangboyu/p/7456606.html
https://studygolang.com/articles/13866?fr=sidebar
context使用的更多相关文章
- Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收
执行环境有全局执行环境和函数执行环境之分,每次进入一个新执行环境,都会创建一个搜索变量和函数的作用域链.函数的局部环境不仅有权访问函数作用于中的变量,而且可以访问其外部环境,直到全局环境.全局执行环境 ...
- spring源码分析之<context:property-placeholder/>和<property-override/>
在一个spring xml配置文件中,NamespaceHandler是DefaultBeanDefinitionDocumentReader用来处理自定义命名空间的基础接口.其层次结构如下: < ...
- spring源码分析之context
重点类: 1.ApplicationContext是核心接口,它为一个应用提供了环境配置.当应用在运行时ApplicationContext是只读的,但你可以在该接口的实现中来支持reload功能. ...
- CSS——关于z-index及层叠上下文(stacking context)
以下内容根据CSS规范翻译. z-index 'z-index'Value: auto | <integer> | inheritInitial: autoApplies to: posi ...
- Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误——SHH框架
SHH框架工程,Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误 1.查看配置文件web.xml中是否配置.or ...
- mono for android Listview 里面按钮 view Button click 注册方法 并且传值给其他Activity 主要是context
需求:为Listview的Item里面的按钮Button添加一个事件,单击按钮时通过事件传值并跳转到新的页面. 环境:mono 效果: 布局代码 主布局 <?xml version=" ...
- Javascript的“上下文”(context)
一:JavaScript中的“上下文“指的是什么 百科中这样定义: 上下文是从英文context翻译过来,指的是一种环境. 在软件工程中,上下文是一种属性的有序序列,它们为驻留在环境内的对象定义环境. ...
- spring源码分析之<context:component-scan/>vs<annotation-config/>
1.<context:annotation-config/> xsd中说明: <xsd:element name="annotation-config"> ...
- 【Android】 context.getSystemService()浅析
同事在进行code review的时候问到我context中的getSystemService方法在哪实现的,他看到了一个ClipBoardManager来进行剪切板存储数据的工具方法中用到了cont ...
- context:component-scan" 的前缀 "context" 未绑定。
SpElUtilTest.testSpELLiteralExpressiontestSpELLiteralExpression(cn.zr.spring.spel.SpElUtilTest)org.s ...
随机推荐
- Vue.js最简单的代码
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- oo第四次总结
1.论述测试与正确性论证的效果差异,比较其优缺点 测试:通过大量测试样例覆盖测试代码,来检测代码功能的实现是否正确是否完善.正确性论证:通过对代码规格和逻辑的严密分析,推论和证明,来验证代码实现的正确 ...
- 现代IM系统中消息推送和存储架构的实现
现代IM系统中消息推送和存储架构的实现-云栖社区-阿里云 https://yq.aliyun.com/articles/253242
- 解决python3 pip安装、更新及yaml安装
问题:python3.6版本使用pip安装第三方库时总是报错 电脑中存在多个python版本写成对应pip版本 解决:pip3 install pyOpenSSL -i http://pypi.dou ...
- 普通Java Web项目为什么lib包要放在WEB-INF下
首先一个项目要编译好之后才能部署到Tomcat中运行. Tomcat运行时如何找编译好的.class文件呢,其实Tomcat下的web项目有两个预置的classpath(就是能找到.class文件的入 ...
- tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)
这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...
- 基于ROS的分布式机器人远程控制平台
基于ROS的分布式机器人远程控制平台 1 结构说明 HiBot架构主要使用C/S架构,其中HibotServer为服务器,Muqutte为消息服务器中间件,HiBotClient为运行在机器人上的 ...
- 原生js标识当前导航位置(给当前导航一个className=active)
导航html结构为: <div class="header2-nav"> <a href="index.html">首页</a&g ...
- 微信网页授权 通过code获取openid 报错40163 code been used
使用好好的微信功能,突然安卓无法正常使用了,苹果的正常. 安卓报错内容: 40163,code been used. 题外话:微信的东西,为何报英文错误呢,装什么13. 实测结果:安卓获取用户信息时 ...
- 解决git冲突造成的Please move or remove them before you can merge
git clean -d -fx “” 其中x —–删除忽略文件已经对git来说不识别的文件d —–删除未被添加到git的路径中的文件f —–强制运行如果你确定这货已经没用了,并且git status ...