go Context的使用
控制并发有两种经典的方式,一种是WaitGroup,另外一种就是Context
WaitGroup的使用
- WaitGroup可以用来控制多个goroutine同时完成
func main() {
var wg sync.WaitGroup
wg.Add(2)
go func() {
time.Sleep(2*time.Second)
fmt.Println("1号完成")
wg.Done()
}()
go func() {
time.Sleep(2*time.Second)
fmt.Println("2号完成")
wg.Done()
}()
wg.Wait()
fmt.Println("好了,大家都干完了,放工")
}
以上例子一定要等到两个goroutine同时做完才会全部完成,这种控制并发方式尤其适用于多个goroutine协同做一件事情的时候。
chan通知
- chan也可以用于控制goroutine,通过chan来控制goroutine是否结束
func main() {
stop := make(chan bool)
go func() {
for {
select {
case <-stop:
fmt.Println("监控退出,停止了...")
return
default:
fmt.Println("goroutine监控中...")
time.Sleep(2 * time.Second)
}
}
}()
time.Sleep(10 * time.Second)
fmt.Println("可以了,通知监控停止")
stop<- true
//为了检测监控过是否停止,如果没有监控输出,就表示停止了
time.Sleep(5 * time.Second)
}
例子中我们通过select判断stop是否接受到值,如果接受到值就表示可以推出停止了,如果没有接受到,就会执行default里面的监控逻辑,继续监控,直到收到stop的通知
以上控制goroutine的方式在大多数情况下可以满足我们的使用,但是也存在很多局限性,比如有很多goroutiine,并且这些goroutine还衍生了其他goroutine,此时chan就比较困难解决这样的问题了
Context
以上问题是存在的,比如一个网络请求request,每个request都需要开启一个goroutine做一些事情。所以我们需要一种可以跟踪goroutine的方案才可以达到控制的目的,go为我们提供了Context
func main() {
ctx, cancel := context.WithCancel(context.Background())
go watch(ctx,"【监控1】")
go watch(ctx,"【监控2】")
go watch(ctx,"【监控3】")
time.Sleep(10 * time.Second)
fmt.Println("可以了,通知监控停止")
cancel()
//为了检测监控过是否停止,如果没有监控输出,就表示停止了
time.Sleep(5 * time.Second)
}
func watch(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Println(name,"监控退出,停止了...")
return
default:
fmt.Println(name,"goroutine监控中...")
time.Sleep(2 * time.Second)
}
}
}
例子中启动了3个监控goroutine进行不断的监控,每一个都使用Context进行跟踪,当我们使用cancel函数通知取消时候,这3个 goroutine都会被结束。所有基于这个context或者衍生出来的子Context都会收到通知,这样就可以进行清理操作最终释放goroutine了
Context接口
Context是一个接口,具体的内容如下:
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
- Deadline方法是获取设置的截止时间的意思,第一个返回式是截止时间,到了这个时间点,Context会自动发起取消请求;第二个返回值ok==false时表示没有设置截止时间,如果需要取消的话,需要调用取消函数进行取消
- Done方法返回一个只读的chan,类型为struct{},我们在goroutine中,如果该方法返回的chan可以读取,则意味着parent context已经发起了取消请求,我们通过Done方法收到这个信号后,就应该做清理操作,然后退出goroutine,释放资源
- Err方法返回取消的错误原因,因为什么Context被取消。
- Value方法获取该Context上绑定的值,是一个键值对,所以要通过一个Key才可以获取对应的值,这个值一般是线程安全的
Context的继承衍生
- context包为我们提供的With系列的函数了
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key, val interface{}) Context
这四个With函数,接收的都有一个partent参数,就是父Context,我们要基于这个父Context创建出子Context的意思
- WithCancel函数,传递一个父Context作为参数,返回子Context,以及一个取消函数用来取消Context
- WithDeadline函数,和WithCancel差不多,它会多传递一个截止时间参数,意味着到了这个时间点,会自动取消Context,当然我们也可以不等到这个时候,可以提前通过取消函数进行取消
- WithTimeout和WithDeadline基本上一样,这个表示是超时自动取消,是多少时间后自动取消Context的意思
- WithValue函数和取消Context无关,它是为了生成一个绑定了一个键值对数据的Context,这个绑定的数据可以通过Context.Value方法访问到
Context使用原则
- 不要把Context放在结构体中,要以参数的方式进行传递
- 以Context作为参数的函数方法,应该把Context作为第一个参数,放在第一位
- 给一个函数方法传递Context的时候,不要传递nil,如果不知道传递什么,就使用context.TODO
- Context的Value相关方法应该传递必须的数据,不要什么数据都使用这个传递
go 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 ...
随机推荐
- 观察者设计模式( Observable类Observer接口)
如果要想实现观察者模式,则必须依靠Java.util包中提供的Observable类和Observer接口. class House extends Observable{ // 表示房子可以被观察 ...
- 百度网盘下载器 PanDownload v2.0
PanDownload是一款坚持以用户体验为中心,畅快淋漓的下载为理念而打造的下载工具. 从2017年2月9日首个版本推出,时至今日已经一年七个月了,首先感谢大家一直以来的支持与建议,促使着我不断地对 ...
- [SQL Server]SQL行转列
SELECT * FROM (select ActionTargetType+actiontype as TypeResult, COUNT(RowGuid) as Number from BanJi ...
- 深入理解python中的yield关键字
想必大家都看过这样的代码: 上面的这段代码会计算0-9的平方并打印出来. 那么问题来了,这段代码和我们要说的东西有什么区别呢? 这里的关键字,yield,我在前面的文章里已经发过了.那么yield是什 ...
- Hibernate核心对象
1.Configuration Configuration 类负责管理Hibernate的配置信息.它包括如下内容: Hibernate运行的底层信息:数据库的URL.用户名.密码.JDBC驱动类,数 ...
- ubuntu常见问题排查
1. ubuntu recovery mode read-only 获取写的权限 1.1. 选择fsck check all file systems 进去直接选择YES就可以了 1.2. 选择roo ...
- 25个增强iOS应用程序性能的提示和技巧 — 中级篇
本文由破船译自:raywenderlich 转载请注明出处:BeyondVincent的博客 _____________ 在开发iOS应用程序时.让程序具有良好的性能是非常关键的.这也是用户所期望的. ...
- Spark系列-核心概念
Spark系列-初体验(数据准备篇) Spark系列-核心概念 一. Spark核心概念 Master,也就是架构图中的Cluster Manager.Spark的Master和Workder节点分别 ...
- HDU 5550 - Game Rooms(DP + 前缀和预处理)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=5550 题意: 一个大楼有n(2≤n≤4000)层,每层可以建一个乒乓球房或者一个游泳房,且每种房间在大楼 ...
- Centos7安装anaconda3
Centos7安装anaconda3 1. 安装bunzip2 yum install bunzip2 2. 下载anaconda3 wget https://repo.anaconda.com/ar ...