在有些资源初始化成本很高,甚至在某些代码路径未触发根本没有必要初始化,可以将对象的创建、配置等耗时操作推迟到真正需要使用时才执行。
sync.Once 是Go标准库提供的线程安全初始化工具,确保初始化代码只执行一次:
var (
resource *MyResource // 需要延迟初始化的资源
once sync.Once // 控制初始化的同步原语
)
func getResource() *MyResource {
once.Do(func() {
resource = &MyResource{
// 初始化代码
}
})
return resource
}
1
2
3
4
5
6
7
8
9
10
11
12
13
特点:
Go 1.21引入了更简洁的sync.OnceValue,适合返回单个值的场景:
var getResource = sync.OnceValue(func() *MyResource {
return &MyResource{
// 初始化代码
}
})
// 使用示例
func main() {
res := getResource() // 第一次调用时初始化
_ = getResource() // 后续调用直接返回缓存值
1
2
3
4
5
6
7
8
9
10
当初始化可能返回错误时,使用sync.OnceValues:
var getConfig = sync.OnceValues(func() (*Config, error) {
return loadConfig("config.yml")
})
func main() {
config, err := getConfig()
if err != nil {
log.Fatal("加载配置失败:", err)
}
// 使用配置...
}
1
2
3
4
5
6
7
8
9
10
11
在以下场景中适合使用延迟初始化:
在有些资源初始化成本很高,甚至在某些代码路径未触发根本没有必要初始化,可以将对象的创建、配置等耗时操作推迟到真正需要使用时才执行。
sync.Once 是Go标准库提供的线程安全初始化工具,确保初始化代码只执行一次:
var (
resource *MyResource // 需要延迟初始化的资源
once sync.Once // 控制初始化的同步原语
)
func getResource() *MyResource {
once.Do(func() {
resource = &MyResource{
// 初始化代码
}
})
return resource
}
1
2
3
4
5
6
7
8
9
10
11
12
13
特点:
Go 1.21引入了更简洁的sync.OnceValue,适合返回单个值的场景:
var getResource = sync.OnceValue(func() *MyResource {
return &MyResource{
// 初始化代码
}
})
// 使用示例
func main() {
res := getResource() // 第一次调用时初始化
_ = getResource() // 后续调用直接返回缓存值
1
2
3
4
5
6
7
8
9
10
当初始化可能返回错误时,使用sync.OnceValues:
var getConfig = sync.OnceValues(func() (*Config, error) {
return loadConfig("config.yml")
})
func main() {
config, err := getConfig()
if err != nil {
log.Fatal("加载配置失败:", err)
}
// 使用配置...
}
1
2
3
4
5
6
7
8
9
10
11
在以下场景中适合使用延迟初始化: