sync.Once
是 Go 语言标准库中提供的一个工具,用于确保某个操作只会执行一次。它的主要作用是在并发环境下,保证某个函数只被调用一次,而且所有并发调用该函数的 goroutine 都会等待该函数执行完成。下面是 sync.Once
的基本用法以及一些优缺点:
初始化 sync.Once
对象:
var once sync.Once
定义只执行一次的函数:
func setup() {
// 一些只需执行一次的操作
}
在需要执行的地方调用 once.Do
方法:
once.Do(setup)
线程安全: sync.Once
确保被调用的函数只会在第一次调用时执行,而且在多个 goroutine 中也不会被重复执行。
简洁: 使用 sync.Once
可以避免手动加锁或其他复杂的并发控制逻辑,使代码更加简洁。
无法传递参数: sync.Once
只能用于不需要参数的函数。如果需要传递参数,通常需要通过其他手段,比如闭包。
不能处理函数执行过程中的错误: 如果被调用的函数发生了错误,sync.Once
无法处理,也就是说,它无法保证函数执行成功,只能保证函数只执行一次。
初始化开销: sync.Once
的初始化会带来一些开销,因此在一些特定场景下,可能会有一些性能影响。但这种影响在大多数情况下是可以忽略的。
package main
import (
"fmt"
"sync"
)
var (
once sync.Once
)
func setup() {
fmt.Println("Init function executed")
}
func main() {
// 多个goroutine调用once.Do,但setup函数只会执行一次
for i := 0; i < 5; i++ {
go func() {
once.Do(setup)
}()
}
// 等待所有goroutine执行完成
fmt.Scanln()
}
在上述示例中,setup
函数只会被执行一次,即使有多个 goroutine 尝试调用 once.Do(setup)
。