Go语言延迟初始化(Lazy Initialization)最佳实践
# 1. 简介
在有些资源初始化成本很高,甚至在某些代码路径未触发根本没有必要初始化,可以将对象的创建、配置等耗时操作推迟到真正需要使用时才执行。
# 2. 延迟初始化实现
# 2.1 sync.Once
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
2
3
4
5
6
7
8
9
10
11
12
13
特点:
- 线程安全,适合并发场景
- 初始化逻辑与业务代码耦合
- 需要额外定义全局变量
# 2.2 sync.OnceValue (Go 1.21+)
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
2
3
4
5
6
7
8
9
10
# 2.3 错误处理方案:sync.OnceValues
当初始化可能返回错误时,使用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
2
3
4
5
6
7
8
9
10
11
# 3. 总结
在以下场景中适合使用延迟初始化:
- 资源初始化成本非常高。
- 为了提高启动性能和内存效率。
- 当并非所有的资源都需要在运行时立即使用,甚至根本不需要使用。
上次更新: 2025/06/14, 16:16:07