说明
此篇博客只介绍 go语言 context
包的用法以及使用场景,适度的做一些源码分析,但不会太深入。go语言的context包设计非常巧妙,非常值得学习,在学习的时候,不要只盯着一个东西学,而要学会迁移学习。比如在这个包当中涉及到了一些别的知识,比如time
包的用法,go语言channel的用法,等等。学完此节,相信你会对我刚刚提到的那些知识点又有新的领悟。
背景介绍
在go语言编写的服务器当中,常常需要在gorutine中处理请求,比如一个http请求,通常会生成一个新的gorutine去进行处理,而这个gorutine当中或许还会新起许多gorutine,比如rpc服务的访问,数据库的访问,等等。当这个请求被取消或者超时的时候,此时这个链条上的gorutine应该被取消执行或者及时退出,以释放系统资源。亦或是这些gorutine需要共享授权令牌等等。有了context,取消,超时,共享链路信息,这一切都变得很简单。
责任与边界
context只是负责通知和传递信息,至于收到通知的gorutine如何做,那是它们自己的事情了。
知识点的准备与复习
这里先准备一些零散的知识点,等会阅读源码的时候会大有裨益,这里准备了一张图,也就是学习了context的用法,实际上你能学到更多的知识点
先来学习或练习使用下面有关时间两个函数
func (t Time) Before(u Time) bool
这个是
Time
类型的方法,表示目前这个时间对象,是否在u
这个时间对象之前,这是两个绝对时间之间的比较;
func Until(t Time) Duration
这个是包级函数,可以理解为,距离
t
这个时间点还有多少时间,也是两个绝对时间的比较,比较的是当前时间
与t
之间,如果t
在当前时间之后,则返回的是正数
,如果t
在当前时间之前,则返回的是负数
因为太简单,这里不写例子了,自己可以写几段代码验证下哦
接下来是通道
我们知道,创建通道可以用make
函数,读写一个无缓冲的通道是会阻塞gorutine的,关闭通道是用close
函数,通道应由写通道的一方关闭,关闭之后,读通道的gorutine不再阻塞
下面我们创建一个通道,阻塞主gorutine,并等待返回
func main() {
ch := make(chan struct{
})
go func() {
time.Sleep(2 * time.Second)
close(ch)
}()
<-ch // 直到通道关闭,将不再阻塞
log.Println("over")
}
2秒之后,通道被关闭了,主gorutine也将不再阻塞
现在咱们再研究研究通道
通道分下面几种
- 双向通道: chan Type
- 单向通道:
- 只读通道: <-chan Type
- 只写通道: chan<- Type
其中,双向通道是可以赋值给单向通道的,而反过来就不行了,使用单向通道的目的主要是为了告诉调用者,这个通道该如何使用
ch := make(chan struct{})
var writeOnlyChan <-chan struct{} = ch
创建了一个双向通道,并且向一个只读通道变量赋值
现在再来看看go语言的定时器
<-time.After(3*time.Second)
After
函数返回一个只读通道,上面表示3秒之后,通道将会收到一个值,另一个比较实用的函数就是AfterFunc
,下面来看看怎么使用
ch := make