闽公网安备 35020302035485号

func main() {
parentCtx := context.Background()
ctx, cancel := context.WithTimeout(parentCtx, 1*time.Millisecond)
defer cancel()
select {
case <-time.After(1 * time.Second):
f1(ctx)
case <-ctx.Done():
f2(ctx)
}
}
func f1(ctx context.Context) {
fmt.Println("堆代码", ctx.Err())
}
func f2(ctx context.Context) {
fmt.Println("堆代码", ctx.Err())
}
输出结果:堆代码 context deadline exceeded
// 第一种方式
func f1(ctx context.Context) {...}
// 堆代码 duidaima.com
// 第二种方式
type T struct {
Ctx context
}
放在函数第一个参数 context 中的话,那每个方法都需要进行传递,用起来就像被 ”污染“ 了一样。每个函数都要层层递进的传下去。非常的显性。放在结构体中的话,按理说 context 是基本对标请求的,每次请求都是不同的 context。这样可能会导致每次都要 NewT() 或是 WithContext。一旦忘了,就很容易埋下隐患。
Go 官方建议中是怎么说的?在 context 标准库的文档中有提到。使用上下文的程序应遵循以下规则,以保持跨包的接口一致:
func DoSomething(ctx context.Context, arg Arg) error {
// ... use ctx ...
}
划重点:官方建议在函数首位参数传递 context,不建议使用结构体传递。可能有同学想说,那是不是 Go 官方就可以放宽 context 的使用建议了?
想太多了...早在 2017 年就有 @Caleb Spare 提出《context: relax recommendation against putting Contexts in structs[1]》,希望 Go 官方放宽对于 context 放入结构体中的建议。但还是处于长期的阻塞状态,没有进一步的相关信息。@Russ Cox 被 @ 了也并没有出来说任何的建议。
