Once se puede usar para ejecutar una acción solo una vez y, a menudo, se usa en el escenario de inicialización de un objeto singleton.
Escenarios de uso de Once
sync.Once solo expone un método Do. Puede llamar al método Do varias veces, pero el parámetro f solo se ejecutará cuando se llame al método Do por primera vez. Aquí f es una función sin parámetros y sin valor de retorno.
func main() {
var once sync.Once
// 第一个初始化函数
f1 := func() {
fmt.Println("in f1")
}
once.Do(f1) // 打印出 in f1
// 第二个初始化函数
f2 := func() {
fmt.Println("in f2")
}
once.Do(f2) // 无输出
}
Una vez se usa a menudo para inicializar recursos singleton, o acceso concurrente a recursos compartidos que solo necesitan inicializarse una vez, o para inicializar recursos de prueba una vez durante la prueba.
syncOnce.go
package main
import (
"fmt"
"sync"
)
var once sync.Once
type single struct {
}
var singleInstance *single
func getInstance() *single {
if singleInstance == nil {
once.Do(
func() {
fmt.Println("Creating single instance now.")
singleInstance = &single{
}
})
} else {
fmt.Println("Single instance already created.")
}
return singleInstance
}
main.go
package main
import (
"fmt"
)
func main() {
for i := 0; i < 30; i++ {
go getInstance()
}
// Scanln is similar to Scan, but stops scanning at a newline and
// after the final item there must be a newline or EOF.
fmt.Scanln()
}
Materiales de referencia: