context
一般来说,goroutine是平级关系,但是通过引进context可以让其有逻辑上的父子关系
也就是,父要子停,子不得不停的意思
揣摩一下哈
手动cancel
package main
import (
"context"
"fmt"
"time"
)
func HandelRequest(ctx context.Context) {
go WriteLog(ctx)
go WriteDB(ctx)
for {
select {
case <-ctx.Done():
fmt.Println("请求处理完毕")
return
default:
fmt.Println("请求处理中……")
time.Sleep(2 * time.Second)
}
}
}
func WriteLog(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("写日志完成")
return
default:
fmt.Println("写日志中……")
time.Sleep(2 * time.Second)
}
}
}
func WriteDB(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("写数据库完成")
return
default:
fmt.Println("写数据库中……")
time.Sleep(2 * time.Second)
}
}
}
func main() {
//WithCancel
ctx, cancel := context.WithCancel(context.Background())
go HandelRequest(ctx)
time.Sleep(5 * time.Second)
fmt.Println("所有子协程都需要结束!")
cancel()
//Just for test whether sub goroutines exit or not
time.Sleep(5 * time.Second)
//WithTimeout
/*ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
go HandelRequest(ctx)
time.Sleep(10 * time.Second)*/
}
分析:
1.ctx, cancel := context.WithCancel(context.Background())通过ctx记录上下文,和cancel用来进行删除
2.当且仅当启动了cancel才会触发<-ctx.Done(),然后三个子协程全部停止
结果:
自动timeout
package main
import (
"context"
"fmt"
"time"
)
func HandelRequest(ctx context.Context) {
go WriteLog(ctx)
go WriteDB(ctx)
for {
select {
case <-ctx.Done():
fmt.Println("请求处理完毕")
return
default:
fmt.Println("请求处理中……")
time.Sleep(2 * time.Second)
}
}
}
func WriteLog(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("写日志完成")
return
default:
fmt.Println("写日志中……")
time.Sleep(2 * time.Second)
}
}
}
func WriteDB(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("写数据库完成")
return
default:
fmt.Println("写数据库中……")
time.Sleep(2 * time.Second)
}
}
}
func main() {
//WithCancel
/*
ctx, cancel := context.WithCancel(context.Background())
go HandelRequest(ctx)
time.Sleep(5 * time.Second)
fmt.Println("所有子协程都需要结束!")
cancel()
//Just for test whether sub goroutines exit or not
time.Sleep(5 * time.Second)*/
//WithTimeout
ctx, _ := context.WithTimeout(context.Background(), 7*time.Second)
go HandelRequest(ctx)
time.Sleep(10 * time.Second)
}
分析:
1.这里改成7秒,足够写出4次工作中了(分别是0,2,4,6)
2.然后7秒该ctx下全部done完,结束工作
结果: