Context
Context
Context
Golang中Context底层是:
type Context interface {Deadline() (deadline time.Time, ok bool)Done() <-chan struct{}Err() errorValue(key any) any
}
- Deadline:返回 context 何时应当超时的时间(
deadline
),以及一个布尔值,指示是否存在这样的截止时间。 - Done:返回一个
<-chan struct{}
通道,当 context 被取消或超时时,该通道会被关闭。 - Err():返回 context 结束的原因,可能的返回值包括
nil
(如果 context 尚未结束)、context.Canceled
(如果 context 被取消)或context.DeadlineExceeded
(如果 context 超时)。 - Value:返回 context 关联的键对应的值,允许在不同的函数、goroutine 之间传递请求范围内的数据。
创建Context
root创建context:
context.Background()
context.TODO()
context创建需要依靠with系列函数:
context有什么用?
- 用于并发控制,控制协程的优雅退出
- 上下文的信息传递
Context就是用来在父子goroutine之间进行值传递以及发送cancel信号的一种机制。
并发控制
1.WithCancel
WithCancel
创建一个新的子 Context
和一个取消函数 CancelFunc
。当调用取消函数时,子 Context
及其所有派生的 Context
都会被取消。这会触发所有通过这个 Context
执行的操作的停止。
package mainimport ("context""fmt""time"
)func main() {ctx, cancel := context.WithCancel(context.Background())go watch(ctx, "g1")go watch(ctx, "g2")time.Sleep(6 * time.Second)fmt.Println("end dd")cancel()time.Sleep(time.Second)
}func watch(ctx context.Context, name string) {for {select {case <-ctx.Done():fmt.Println("end ", name)returndefault:fmt.Println("watch ", name)time.Sleep(time.Second)}}
}
2.WithDeadline
WithDeadline
创建一个新的子 Context
,并指定一个绝对的截止时间(deadline
)。当当前时间超过这个截止时间时,子 Context
会自动取消。
package mainimport ("context""fmt""time"
)func main() {ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(4*time.Second)) // 设置超时时间为4sdefer cancel()go watch(ctx, "g1")go watch(ctx, "g2")time.Sleep(6 * time.Second)fmt.Println("end dd")
}func watch(ctx context.Context, name string) {for {select {case <-ctx.Done():fmt.Println("end ", name)returndefault:fmt.Println("watch ", name)time.Sleep(time.Second)}}
}
3.WithTimeout
WithTimeout
创建一个新的子 Context
,并指定一个相对时间(timeout
)。子 Context
会在超出这个时间段后自动取消。
package mainimport ("context""fmt""time"
)func main() {ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second) // 设置超时时间为4sdefer cancel()go watch(ctx, "g1")go watch(ctx, "g2")time.Sleep(6 * time.Second)fmt.Println("end dd")
}func watch(ctx context.Context, name string) {for {select {case <-ctx.Done():fmt.Println("end ", name)returndefault:fmt.Println("watch ", name)time.Sleep(time.Second)}}
}
4.WithValue
WithValue
创建一个新的子 Context
,并将一个键值对 (key
, value
) 存储在该 Context
中。其他代码可以通过 ctx.Value(key)
方法来访问这个值。
package mainimport ("context""fmt""time"
)func func1(ctx context.Context) {fmt.Println("name is ", ctx.Value("name").(string))
}func main() {ctx := context.WithValue(context.Background(), "name", "张三")go func1(ctx)fmt.Println(ctx.Value("name"))time.Sleep(time.Second)
}