别再乱用 `sync.Once` 了!这几个细节能让你避免死锁

简介: 别再乱用 `sync.Once` 了!这几个细节能让你避免死锁

别再乱用 sync.Once 了!这几个细节能让你避免死锁

在 Go 中,sync.Once 是保证某个函数只执行一次的利器,常用于单例模式、懒加载等场景。但用不对,它可能成为你代码中的“隐形炸弹”。

典型错误:在 Do 方法中嵌套调用 Do

var (
    once sync.Once
    data string
)

func initData() {
   
    once.Do(func() {
   
        // 假设这里又调用了 once.Do
        once.Do(func() {
   
            data = "initialized"
        })
    })
}

这会直接死锁! 因为 sync.Once 内部通过 mutexatomic 控制状态,第一次 Do 未完成时,第二次 Do 会阻塞等待,形成死锁。

另一个陷阱:在 Do 中 panic

如果 once.Do 传入的函数 panicsync.Once 会认为该次执行“已完成”。下次再调用 Do 时,函数将不再执行。

once.Do(func() {
   
    panic("something wrong")
})
// 后续调用 once.Do 不会重新执行

这意味着你的初始化逻辑可能永久失效。

最佳实践

  1. 避免嵌套:不要在 once.Do 的回调函数内对同一个 once 再次调用 Do
  2. 处理 panic:若 Do 内的代码可能 panic,务必用 recover 捕获,并考虑重置 sync.Once(虽然官方不提供重置方法,但可通过替换 once 变量实现)。
  3. 简单至上sync.Once 适合简单的初始化,复杂逻辑建议使用 init() 函数或显式的 sync.Mutex 控制。

用好 sync.Once,让你的 Go 并发代码更稳健!

目录
相关文章
|
26天前
|
安全 JavaScript 前端开发
5个实用的PHP技巧,提升你的开发效率
5个实用的PHP技巧,提升你的开发效率
|
26天前
|
索引 Python
5个让你代码更“Pythonic”的优雅技巧
5个让你代码更“Pythonic”的优雅技巧
289 133
|
26天前
|
安全 PHP
PHP 8+ 实用技巧:提升代码质量与效率
PHP 8+ 实用技巧:提升代码质量与效率
|
26天前
|
Go
Go技巧:用Context包优雅管理goroutine生命周期
Go技巧:用Context包优雅管理goroutine生命周期
582 133
|
26天前
|
安全 PHP
PHP 8 实用技巧:让你的代码更优雅高效
PHP 8 实用技巧:让你的代码更优雅高效
|
10天前
|
缓存 数据库连接 索引
五个提升Python水平的实用技巧
五个提升Python水平的实用技巧
179 134
|
10天前
|
缓存 Python
5个让你惊艳的Python冷门技巧,工作效率翻倍
5个让你惊艳的Python冷门技巧,工作效率翻倍
186 134
|
16天前
|
安全 数据库 Python
让Python代码更优雅:深入理解上下文管理器
让Python代码更优雅:深入理解上下文管理器
209 134
|
16天前
|
Python
让你的Python代码更优雅:3个必知的实用技巧
让你的Python代码更优雅:3个必知的实用技巧
208 134
|
26天前
|
安全 Go
五个让你的Go代码更优雅的实用技巧
五个让你的Go代码更优雅的实用技巧
265 133