func main() {
var v int64
wg := sync.WaitGroup{}
ctx := context.WithValue(context.Background(), "myKey", &v)
for i := 0; i < 10; i++ {
wg.Add(1)
go func(ctx context.Context, key string) {
// 取出来的是interface{},需要先断言成我们需要的类型
value := ctx.Value(key).(*int64)
// 原子操作,并发安全
atomic.AddInt64(value, 1)
wg.Done()
}(ctx, "myKey")
}
wg.Wait()
// 类型断言成*int64然后解引用
fmt.Println(*(ctx.Value("myKey").(*int64)))
}
运行结果会打印出10,因为有10个goroutine分别对v原子地加了一。
当然,引入类型断言后代码复杂度有所提升,但数据的共享却方便了,你可以基于带值的context为parent继续构建可以取消或超时的context,同时可以在其中分发数据而无需将其作为参数传递。
context包的使用就是这么简单,还有更多对于context的应用,这里就不一一列举了,希望各位读者在以后的开发中能够多加利用context包,写出健壮的更优雅的代码。
参考
context包官方文档
官方博客的介绍