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 ...
随机推荐
- linux 标注主机别名
vi /etc/bashrc # Turn on checkwinsize shopt -s checkwinsize [ "$PS1" = "\\s-\\v\\\$ ...
- dynamic 类型不能访问属性
x //解决方案ProjectTest.项目A里面public object r(){ ,name = "zf"}; } //解决方案ProjectTest.项目B里面 publi ...
- 安装配置Greenplum
一.规划 1.服务器: 192.168.0.191 gpdb01 # master 192.168.0.192 gpdb02 # primary segment . ...
- python 函数enumerate(x,y)的用法
enumerate(x,y)函数是把元组tuple.字符串str.列表list里面的元素遍历和索引组合,其用法与range()函数很相似, 下面示例enumerate(x,y)用法以及range(x) ...
- 共享文件 Ubuntu下安装Samba与Windows
Author:Xianghai Ding.Date:2019/01/08**************************************************************安装 ...
- libcurl.a 跨平台
编译成libxxx.a文件后, 通过lipo把多个不同架构的文件合并起来成为一个文件 在build setting 设置 head search path , library search path ...
- selenium--鼠标事件
鼠标事件perform() #执行所有ActionChains中存储的行为context_click() #右击事件double_click() #双击事件drag_and_drop(source,t ...
- 如何通过轮询实现session自动注销
每个用户在访问完网站后,经常会忽略注销账户,session默认存在的时间为30分钟,因此如果需要立即关闭session而又不用麻烦用户则可以通过轮询的方法来实现. 以下通过代码的讲解: xml配置文件 ...
- HTML5的优点与缺点?
优点:a.网络标准统一.HTML5本身是由W3C推荐出来的. b.多设备.跨平台 c.即时更新,提高可用性和改进用户的友好体验: d.有几个新的标签,这将有助于开发人员定义重要的内容: e.可以给站点 ...
- 一道有趣的JS问题
function Foo() { getName = function () { alert (1); }; return this; } Foo.getName = function () { al ...