一次性控制多个协程状态
【摘要】 1 简介控制协程全部退出,控制协程goroutine,使其在某个信号到底时协程就退出在 Go 里,最正宗、最通用、也是官方推荐的方式是:context + signal。本文按「正确姿势 → 常见写法 → 易踩坑」慢慢讲清楚。 2 推荐方案:context.WithCancel + os/signal基本思路,主协程监听系统信号(如 SIGINT / SIGTERM)收到信号后 canc...
1 简介
控制协程全部退出,控制协程goroutine,使其在某个信号到底时协程就退出
在 Go 里,最正宗、最通用、也是官方推荐的方式是:context + signal。

本文按「正确姿势 → 常见写法 → 易踩坑」慢慢讲清楚。
2 推荐方案:context.WithCancel + os/signal
基本思路,主协程监听系统信号(如 SIGINT / SIGTERM)
收到信号后 cancel()
goroutine 里 select 监听 ctx.Done(),主动退出
强烈推荐代码 标准示例
package main
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("worker exit")
return
default:
fmt.Println("working...")
time.Sleep(time.Second)
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
go worker(ctx)
// 监听信号
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
<-sigCh // 阻塞,直到收到信号
fmt.Println("receive signal, exiting...")
cancel() // 通知所有 goroutine
time.Sleep(time.Second) // 等待 goroutine 优雅退出
}
- 优点
Go 官方推荐
可层层传递(HTTP / RPC / DB 都支持)
支持 timeout / deadline
非常适合微服务
3 更优雅:signal.NotifyContext(Go 1.16+)
这是现在最爽的写法
ctx, stop := signal.NotifyContext(
context.Background(),
syscall.SIGINT,
syscall.SIGTERM,
)
defer stop()
go worker(ctx)
<-ctx.Done()
fmt.Println("main exit")
收到信号 ⇒ ctx.Done() 自动关闭
不用自己写 channel + signal.Notify
多个 goroutine 一起退出
for i := 0; i < 3; i++ {
go func(id int) {
for {
select {
case <-ctx.Done():
fmt.Printf("worker %d exit\n", id)
return
default:
time.Sleep(time.Second)
}
}
}(i)
}
一个 cancel,全部退出
常见坑的 不推荐方案
错误:用 bool 标志位
var stop bool
缺点:
数据竞争
不可组合
不可传递
强杀 goroutine
Go 不支持从外部 kill goroutine
必须靠 goroutine 自己退出
4 适合简单场景的channel 控制
stop := make(chan struct{})
go func() {
<-stop
fmt.Println("exit")
}()
close(stop)
不支持 timeout / deadline / 层级控制
5 小结
信号一来 → cancel context → 所有 goroutine 自己优雅退出。
实战建议
场景 建议
服务 / 守护进程 context + signal
HTTP / gRPC 直接用 request.Context
简单工具 signal.NotifyContext
多层调用 context 一路往下传
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)