简言
WithCancel()函数接受一个 Context 并返回其子Context和取消函数cancel
新创建协程中传入子Context做参数,且需监控子Context的Done通道,若收到消息,则退出
需要新协程结束时,在外面调用 cancel 函数,即会往子Context的Done通道发送消息
注意:当 父Context的 Done() 关闭的时候,子 ctx 的 Done() 也会被关闭
实验步骤
利用根Context创建一个父Context,使用父Context创建一个协程,
利用上面的父Context再创建一个子Context,使用该子Context创建一个协程
一段时间后,调用父Context的cancel函数,会发现父Context的协程和子Context的协程都收到了信号,被结束了
package main
import (
"context"
"fmt"
"log"
"os"
"time"
)
func ctxjob() {
ctx := context.Background()
subctx, c := context.WithCancel(ctx)
action := func(sctx context.Context, id int) {
for {
select {
case <-sctx.Done():
fmt.Println("action done exit.", id)
return
default:
fmt.Println("action running...", id)
time.Sleep(1 * time.Second)
}
}
}
go action(subctx, 1)
sub2ctx, _ := context.WithCancel(subctx)
go action(sub2ctx, 2)
time.Sleep(10 * time.Second)
fmt.Println("stop action")
c()
time.Sleep(1 * time.Second)
fmt.Println("stop action done.")
}
func main() {
// pullRedis()
ctxjob()
}
输出:
PS E:\bug\go-leo-t> go build main.go
PS E:\bug\go-leo-t> .\main.exe
action running... 2
action running... 1
action running... 1
action running... 2
action running... 1
action running... 2
action running... 2
action running... 1
action running... 1
action running... 2
action running... 2
action running... 1
action running... 2
action running... 1
action running... 1
action running... 2
action running... 2
action running... 1
action running... 1
action running... 2
stop action
action done exit. 2
action done exit. 1
stop action done.