背景
在实际编程中goroutine会拉起新的goroutine,新goroutine又会拉出另一个新goroutine,单纯使用退出通知机制会比较复杂,采用context标准库的做法,对“树型”的goroutine调用,提供退出通知和元数据传递。
实现例子
package main
import (
"context"
"fmt"
"time"
)
type otherContext struct {
context.Context
}
func work(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Printf("%s get msg to cancel\n", name)
return
default:
fmt.Printf("%s is running \n", name)
time.Sleep(1 * time.Second)
}
}
}
func workWithvalue(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Printf("%s get msg to cancel \n", name)
return
default:
value := ctx.Value("key").(string)
fmt.Printf("%s is running, value is %s \n", name, value)
time.Sleep(1 * time.Second)
}
}
}
func main() {
ctxa, cancel := context.WithCancel(context.Background())
go work(ctxa, "work1")
tm := time.Now().Add(3 * time.Second)
ctxb, _ := context.WithDeadline(ctxa, tm)
go work(ctxb, "work2")
oc := otherContext{ctxb}
ctxc := context.WithValue(oc, "key", "hello test context!")
go workWithvalue(ctxc, "work3")
time.Sleep(10 * time.Second)
cancel()
time.Sleep(5 * time.Second)
fmt.Println("test end!")
}
运行结果