Go并发三板斧:掌握这些技巧,你的代码更高效
Go语言凭借其原生并发支持成为后端开发的热门选择。但用好 goroutine 和 channel 并不简单。今天分享三个实用技巧,助你写出更健壮的并发代码。
一、用 sync.Once 确保单次执行
在并发环境中,某些初始化操作只需执行一次,比如配置加载。sync.Once 能保证无论多少 goroutine 调用,函数只执行一次。
var once sync.Once
var config *Config
func loadConfig() {
config = load() // 假设 load 从文件或网络加载配置
}
func GetConfig() *Config {
once.Do(loadConfig)
return config
}
无论多少个 goroutine 同时调用 GetConfig,loadConfig 都只运行一次,安全又高效。
二、使用 errgroup 管理协程
标准库的 sync.WaitGroup 只能等待,无法传递错误。golang.org/x/sync/errgroup 包弥补了这一缺陷。它允许你启动一组 goroutine,并等待所有完成或第一个错误返回。
import "golang.org/x/sync/errgroup"
g, ctx := errgroup.WithContext(context.Background())
for _, task := range tasks {
task := task // 捕获迭代变量
g.Go(func() error {
return process(task) // process 可能返回错误
})
}
if err := g.Wait(); err != nil {
// 处理错误(可能是第一个返回的错误)
}
配合 ctx 还能在出错时自动取消其他 goroutine,非常实用。
三、channel 的关闭与广播
关闭 channel 可以同时通知多个接收者。利用这一特性实现优雅退出。创建一个 stop channel,所有 worker 监听,主程序关闭 channel 即可广播停止信号。
stop := make(chan struct{
})
workers := 5
for i := 0; i < workers; i++ {
go func() {
for {
select {
case <-stop:
return // 收到停止信号,退出
default:
// 正常工作
doWork()
}
}
}()
}
// 需要停止所有 worker 时
close(stop) // 广播停止信号,所有 worker 都会退出
这种方式无需维护 worker 列表,简洁且可靠。
掌握这些技巧,你的 Go 并发代码将更安全、更清晰。快去项目中试试吧!