Background() 这个函数返回一个空 context。这只能用于高等级(在 main 或顶级请求处理中)。通常用于派生的其他 context 。
TODO() 这个函数也是创建一个空 context。也只能用于高等级或当您不确定使用什么 context,或函数以后会更新以便接收一个 context 。这意味您(或维护者)计划将来要添加 context 到函数。
它与 background 完全相同。不同的是,静态分析工具可以使用它来验证 context 是否正确传递,这是一个重要的细节,因为静态分析工具可以帮助在早期发现潜在的错误,并且可以连接到 CI/CD 管道。
WithValue() 此函数接收 context 并返回派生 context,其中值 val 与 key 关联,并通过 context 树与 context 一起传递。这意味着一旦获得带有值的 context,从中派生的任何 context 都会获得此值。不建议使用 context 值传递关键参数,而是函数应接收签名中的那些值,使其显式化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package mainimport ( "context" "fmt" ) func main () { ctx := context.WithValue(context.Background(), "trace_id" , "88888888" ) ctx = context.WithValue(ctx, "session" , 1 ) process(ctx) } func process (ctx context.Context) { session, ok := ctx.Value("session" ).(int ) fmt.Println(ok) if !ok { fmt.Println("something wrong" ) return } if session != 1 { fmt.Println("session 未通过" ) return } traceID := ctx.Value("trace_id" ).(string ) fmt.Println("traceID:" , traceID, "-session:" , session) }
WithCancel() 返回派生 context 和取消函数。只有创建它的函数才能调用取消函数来取消此 context。如果您愿意,可以传递取消函数,但是,强烈建议不要这样做。这可能导致取消函数的调用者没有意识到取消 context 的下游影响。可能存在源自此的其他 context,这可能导致程序以意外的方式运行。简而言之,永远不要传递取消函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package mainimport ( "context" "fmt" "time" ) func main () { ctx, cancel := context.WithCancel(context.Background()) flags := checkFlag(ctx) for n := range flags { if n >= 10 { cancel() fmt.Println("main 进行 chanel()" ) break } } fmt.Println("main chanel()以后" ) time.Sleep(2 * time.Second) } func checkFlag (ctx context.Context) <-chan int { c := make (chan int ) n := 0 go func () { for { select { case <-ctx.Done(): fmt.Printf("checkFlag函数 Done()\n" ) return case c <- n: n++ fmt.Printf("系数加1\n" ) } } }() return c }
WithDeadline() 此函数返回其父项的派生 context,当截止日期超过或取消函数被调用时,该 context 将被取消。例如,您可以创建一个将在以后的某个时间自动取消的 context,并在子函数中传递它。当因为截止日期耗尽而取消该 context 时,获此 context 的所有函数都会收到通知去停止运行并返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package mainimport ( "context" "fmt" "time" ) func main () { ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second * 2 )) defer cancel() flags := checkFlag(ctx) select { case <-ctx.Done(): fmt.Printf("main 挂起2秒后,值加到了 %d\n" , <-flags) } fmt.Println("main chanel()以后" ) time.Sleep(3 * time.Second) } func checkFlag (ctx context.Context) <-chan int { c := make (chan int ) n := 0 go func () { for { time.Sleep(time.Millisecond * 100 ) select { case <-ctx.Done(): c<-n fmt.Printf("checkFlag函数 Done()\n" ) return default : n++ fmt.Printf("系数加1\n" ) } } }() return c }
WithTimeout() 此函数类似于 context.WithDeadline。不同之处在于它将持续时间作为参数输入而不是时间对象。此函数返回派生 context,如果调用取消函数或超出超时持续时间,则会取消该派生 context。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package mainimport ( "context" "fmt" "time" ) func main () { ctx, cancel := context.WithTimeout(context.Background(), time.Second * 2 ) defer cancel() flags := checkFlag(ctx) select { case <-ctx.Done(): fmt.Printf("main 挂起2秒后,值加到了 %d\n" , <-flags) } fmt.Println("main chanel()以后" ) time.Sleep(3 * time.Second) } func checkFlag (ctx context.Context) <-chan int { c := make (chan int ) n := 0 go func () { for { time.Sleep(time.Millisecond * 100 ) select { case <-ctx.Done(): c<-n fmt.Printf("checkFlag函数 Done()\n" ) return default : n++ fmt.Printf("系数加1\n" ) } } }() return c }