Go 1.17中提出,主要提供子孙goroutine的通知关闭的统一解决方法
-
Context接口
type Context interface { Deadline() // 截止时间 Done() // 手动Cancel时接收到值 Err() // 错误 Value() // 存储值 }
-
Context接口的两个默认实现
- Background
顶层Context
- TODO
暂时不知道具体使用场景时使用
- Background
-
三种实现方式
-
WithCancel
// 父goroutine中调用cancel()时,子goroutine的ctx.Done()接收到值,即:关闭的通知信号 var c = 1 func doSome(i int) error { c++ fmt.Println(c) if c > 3 { return errors.New("err occur") } return nil } func speakMemo(ctx context.Context, cancelFunc context.CancelFunc) { for { select { case <-ctx.Done(): fmt.Printf("ctx.Done") return default: fmt.Println("exec default func") err := doSome(3) if err != nil { fmt.Printf("cancelFunc()") cancelFunc() } } } } func main() { rootContext := context.Background() ctx, cancelFunc := context.WithCancel(rootContext) go speakMemo(ctx, cancelFunc) time.Sleep(time.Second * 5) }
-
WithDeadline
// 指定时间终止,规定还是最终需要主动调用cancel const shortDuration = 1 * time.Millisecond func main() { d := time.Now().Add(shortDuration) ctx, cancel := context.WithDeadline(context.Background(), d) // Even though ctx will be expired, it is good practice to call its // cancellation function in any case. Failure to do so may keep the // context and its parent alive longer than necessary. defer cancel() select { case <-time.After(1 * time.Second): fmt.Println("overslept") case <-ctx.Done(): fmt.Println(ctx.Err()) } }
-
WithValue
// goroutine直接传值 func main() { type favContextKey string f := func(ctx context.Context, k favContextKey) { if v := ctx.Value(k); v != nil { fmt.Println("found value:", v) return } fmt.Println("key not found:", k) } k := favContextKey("language") ctx := context.WithValue(context.Background(), k, "Go") f(ctx, k) f(ctx, favContextKey("color")) }
-
记录自己的学习历程!