并发控制方式
sync.waitGroup 一个整体任务的部分任务,适用于自然结束的
select+channel 灵活些但是需要设置channel,适用于一个协程环境
context 适用于一个或多个协程结束
contxet示例并发控制
// 使用 Context 控制多个 goroutine
func contextPart4() {
ctx, cancel := context.WithCancel(context.Background())
go watch(ctx, "task 1")
go watch(ctx, "task 2")
go watch(ctx, "task 3")
time.Sleep(10 * time.Second)
log.Println("可以通知任务结束")
cancel()
time.Sleep(5 * time.Second)
}
func watch(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
log.Println(name + " 任务即将要退出了...")
return
default:
log.Println(name + " goroutine 继续处理任务中...")
time.Sleep(2 * time.Second)
}
}
}
context示例
上下文传递
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("小米")
ctx := context.WithValue(context.Background(), k, "小米")
f(ctx, k)
f(ctx, favContextKey("小红"))
}
found value: 小米
key not found: 小红
接口
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
Deadline:获取当前 context 的截止时间。
Done:获取一个只读的 channel,类型为结构体。
可用于识别当前 channel 是否已经被关闭,其原因可能是到期,也可能是被取消了。
Err:获取当前 context 被关闭的原因。
Value:获取当前 context 对应所存储的上下文信息
--------------------------------------------------------------------
type canceler interface {
cancel(removeFromParent bool, err error)
Done() <-chan struct{}
}
cancel:调用当前 context 的取消方法。
Done:与前面一致,可用于识别当前 channel 是否已经被关闭。
--------------------------------------------------------------------
type emptyCtx int
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func (*emptyCtx) Done() <-chan struct{} {
return nil
}
func (*emptyCtx) Err() error {
return nil
}
func (*emptyCtx) Value(key interface{}) interface{} {
return nil
}
context 包中定义了 Background 函数和 TODO 函数,他们会返回一个空的 ctx
background 一般作为根 ctx,
todo 一般是作为一个临时 ctx 使用
--------------------------------------------------------------------
结构体cancelCtx & 函数 WithCancel
cancelCtx 是一个不对外暴露的 ctx,可以使用 WithCancel 函数,
传入一个父 ctx 来生成一个可取消的 ctx
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
结构体 timerCtx & 函数 WithDeadline & 函数 WithTimeout
timerCtx 也是一个不对外暴露的上下文结构
WithTimeout WithDeadline暴露
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
结构体 valueCtx & 函数 WithValue
valueCtx 同样也是不对外暴露的,
WithValue 函数来拿到 valueCtx 的上下文结构体
func WithValue(parent Context, key, val interface{}) Context