概述
一、应用
Go服务器的每个请求都有自己的goroutine,而有的请求为了提高性能,会经常启动额外的goroutine处理请求,当该请求被取消或超时,该请求上的所有goroutines应该退出,防止资源泄露。
二、使用
1.Context接口
type Context interface {
//Dealine()函数返回上下文应该取消的时间,如果没有设置超时时间则ok为false
Deadline() (deadline time.Time, ok bool)
//Done()返回一个close的channel用于关闭该上下文,如果该上下文不能关闭则返回nil
//当cancel函数被调用时会使用Done去关闭,
//当deadline到期后会使用Done去关闭
Done() <-chan struct{}
//如果Done未关闭,则Err返回nil
//如果Done已关闭,则返回非空的error解释原因
Err() error
//Value通过key获取该key在上下文中关联的值,如果该key没有关联的值,则返回nil
//多次调用同一个key,返回的结果是一样的
Value(key interface{}) interface{}
}
2.Context常用初始化创建方法
1).func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
2). func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
3) .func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
注:WithTimeout 等同于 WithDeadline(parent, time.Now().Add(timeout)).
三、示例:
1.常用方法示例
/*
context.WithCancel()
*/
func withCancel() {
ctx,cancel := context.WithCancel(context.Background())
go doStuff(ctx)
//过7s取消该context
time.Sleep(time.Second*7)
cancel()
time.Sleep(time.Second*2)
}
/*
context.WithTimeout()
*/
func withTimeout() {
ctx,cancel := context.WithTimeout(context.Background(),time.Second*7)
go doStuff(ctx)
//退出ctx时间:在timeout和调用cancel时间点的最小值
time.Sleep(time.Second*5)
//time.Sleep(time.Second*10)
cancel()
time.Sleep(time.Second*2)
}
/*
context.WithDeadline()
WithTimeout 等价于 WithDeadline(parent, time.Now().Add(timeout))
*/
func withDeadline() {
ctx,cancel := context.WithDeadline(context.Background(),time.Now().Add(time.Second*7))
go doStuff(ctx)
//退出ctx时间:在timeout和调用cancel时间点的最小值
time.Sleep(time.Second*5)
//time.Sleep(time.Second*10)
cancel()
time.Sleep(time.Second*2)
}
func doStuff(ctx context.Context) {
for {
time.Sleep(time.Second)
select {
case <-ctx.Done():
log.Println("done")
return
default:
log.Println("working")
}
}
}
func main() {
log.Println("withCancel start work!")
withCancel()
log.Println("withCancel work over!")
log.Println("----------------------------------------------")
log.Println("withTimeout start work!")
withTimeout()
log.Println("withTimeout work over!")
log.Println("----------------------------------------------")
log.Println("withDeadline start work!")
withDeadline()
log.Println("withDeadline work over!")
log.Println("----------------------------------------------")
}
2.当parent取消时,所有子context取消
func main() {
testCtx()
time.Sleep(time.Minute*2)
}
func testCtx() {
ctx,_ := context.WithTimeout(context.Background(),5*time.Second)
//defer cancel()
go func() {
select {
case <- ctx.Done():
fmt.Println("ctx done:",time.Now())
case <- time.After(time.Minute):
fmt.Println("ctx timeout")
}
}()
ctxChild1,_ := context.WithTimeout(ctx,10*time.Second)
go func() {
select {
case <- ctxChild1.Done():
fmt.Println("ctxChild1 done:",time.Now())
case <- time.After(time.Minute):
fmt.Println("ctxChild1 timeout")
}
}()
ctxChild2,_ := context.WithTimeout(ctx,15*time.Second)
go func() {
select {
case <- ctxChild2.Done():
fmt.Println("ctxChild2 done:",time.Now())
case <- time.After(time.Minute):
fmt.Println("ctxChild2 timeout")
}
}()
ctxDescendant , _ := context.WithCancel(ctxChild1)
go func() {
select {
case <- ctxDescendant.Done():
fmt.Println("ctxDescendant done:",time.Now())
case <- time.After(time.Minute):
fmt.Println("ctxDescendant timeout")
}
}()
}
从结果可以看到当parent取消时,所有的子级context都会取消
参考地址:
https://www.jianshu.com/p/d24bf8b6c869?utm_campaign=studygolang.com&utm_medium=studygolang.com&utm_source=studygolang.com
https://www.jianshu.com/p/b7202f2bb477?utm_campaign=studygolang.com&utm_medium=studygolang.com&utm_source=studygolang.co
最后
以上就是现代鸡翅为你收集整理的Golang中Context学习的全部内容,希望文章能够帮你解决Golang中Context学习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复