sync.Once的作用正是为了防止在多goroutine并发执行时,对某个操作进行重复的初始化。它确保即使在高度并发的场景下,某些高成本的初始化操作(比如创建资源、加载配置、设置全局状态等)也只会被执行一次。
比如进行下面的这个例子,建立数据库连接:
var (
db *sql.DB
once sync.Once
dbDial = func() (*sql.DB, error) {
dsn := "user:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
return sql.Open("mysql", dsn)
}
)
func GetDB(ctx context.Context) (*sql.DB, error) {
var err error
once.Do(func() {
db, err = dbDial()
if err != nil {
log.Fatalf("Failed to establish database connection: %v", err)
}
// 检查连接是否有效并设置适当的重试策略或超时
if err = db.PingContext(ctx); err != nil {
log.Fatalf("Failed to ping the database: %v", err)
}
})
return db, err
}