前言
在使用go开发中,有时要监听方法是否正常完成或者是否超时、取消等,可以用到go的上下文信息,context可以用来在goroutine之间传递上下文信息
context使用
WithCancel
WithCancel可以创建一个可取消的子 Context,然后当作参数传给 goroutine 使用,例如
package main
import (
"context"
"log"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go func() {
log.Println("执行开始================")
time.Sleep(3 * time.Second)
cancel()
}()
select {
case <-ctx.Done():
log.Println("==============执行结束")
}
}
输出结果为
执行了cancel()之后,阻塞就结束了
WithTimeout
WithTimeout可以创建一个可取消的子 Context
package main
import (
"context"
"log"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
go func() {
log.Println("执行开始================")
time.Sleep(3 * time.Second)
cancel()
}()
select {
case <-ctx.Done():
log.Println("==============执行结束", ctx.Err())
}
}
输出结果为
2秒之后,没有执行cancel(),就超时了
WithValue
WithValue可以用来传递上下文数据
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
value := context.WithValue(ctx, "aa", "aaa")
go run(value)
time.Sleep(3 * time.Second)
cancel()
time.Sleep(3 * time.Second)
}
func run(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Printf("任务结束:%v\n", ctx.Value("aa"))
return
default:
fmt.Printf("取到的值为: %v\n", ctx.Value("aa"))
time.Sleep(time.Second * 2)
}
}
}
输出结果为
总结
可以合理的利用context来传递goroutine之间的信息,而且context是线程安全的