一、Go 如何让子程序自动退出
func main() {
// context.WithTimeout,返回一个实现context的结构体,有超时返回的功能
// context.Background() 是一个固定的参数,表示根节点
// 5*time.Second 表示设置5秒超时,超过两秒子程序会自动退出。
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
// 开启协程
go worker2(ctx)
// 主程序等待五秒,防止自动退出
// 当在函数前加 go 意味着这个函数开了一个协程执行函数,主线程会跳过这段
// 当线程结束,不管字协程是否结束,会自动结束,所以我们等待10秒,字协程等待五秒主线程也不会结束。
time.Sleep(time.Second * 10)
fmt.Println("主线程结束")
}
worker2函数设定一个for无限循环函数,只有当 ctx.Done()通道有值的时候才会触发break。
func worker2(ctx context.Context) {
// break Loop 跳到这里,并且跳过for{}
LOOP:
for {
select {
// ctx 传入的时候第二个参数设定了5秒 time.Second,当时间到了,ctx.Done(一个通道),通道中会传入值,
// 这样 <-ctx.Done() 就能执行力,否则 select就一直执行default{}
case <-ctx.Done():
fmt.Println("ctx.Done()通道经过5秒接受到信息,退出")
break LOOP
default:
fmt.Println("执行default,并停止1秒")
time.Sleep(time.Second)
}
}
}
二、Go 如何让主协程控制子协程退出
主线程调用canf()方法,子协程就会自动退出了。
func main() {
// 上面采用了 context.WithTimeout方法,这次使用 context.WithCancel,并让左边的 _ 改成canf
ctx, canf := context.WithCancel(context.Background())
// 开启协程
go workerWithCancel(ctx)
//主程序等待五秒,防止自动退出
//当在函数前加 go 意味着这个函数开了一个协程执行函数,主线程会跳过这段
//当线程结束,不管字协程是否结束,会自动结束,所以我们等待10秒,字协程等待五秒主线程也不会结束。
time.Sleep(time.Second * 2)
// 调用canf函数,ctx.Done() 通道自己会赋值,这样子协程就会break了
canf()
fmt.Println("主线程结束")
}
func workerWithCancel(ctx context.Context) {
// break Loop 跳到这里,并且跳过for{}
LOOP:
for {
select {
// 当main调用WithCancel的返回参数canf,canf调用的时候,ctx.Done(一个通道),通道中会传入值
// 这样 <-ctx.Done() 就能执行力,否则 select就一直执行default{}
case <-ctx.Done():
fmt.Println("ctx.Done()通道经过5秒接受到信息,退出")
break LOOP
default:
fmt.Println("执行default,并停止1秒")
time.Sleep(time.Second)
}
}
}