golang中的sync.Once

本文介绍了Go语言中的sync.Once类型,展示了如何利用它确保函数仅执行一次。在给出的示例中,尽管循环执行了100次,但do函数只打印了一次数字2,体现了sync.Once的单例特性。

golang中的sync.Once可以让代码只执行一次,比如:

func do() {
   fmt.Println(2)
}
func main() {
   a := sync.Once{}
   for i := 0; i < 100; i++ {
      go a.Do(do)
   }
}

输出为:

GOROOT=E:\go #gosetup
GOPATH=E:\go_program;E:\go的环境变量 #gosetup
E:\go\bin\go.exe build -o C:\Windows\Temp\GoLand\___go_build_gee_123.exe gee/123 #gosetup
C:\Windows\Temp\GoLand\___go_build_gee_123.exe
2

Process finished with the exit code 0
 

Go 语言中,`sync.Once` 是一个用于确保某个函数在并发环境中仅执行一次的结构体。它特别适用于一次性初始化操作,例如初始化配置、连接池或全局变量的初始化等场景。以下是一个典型的使用示例: ```go package main import ( "fmt" "sync" "time" ) var once sync.Once var onceBody = func() { fmt.Println("Only once") } func main() { for i := 0; i < 5; i++ { go func(i int) { once.Do(onceBody) fmt.Println("i=", i) }(i) } time.Sleep(time.Second) // 睡眠 1s 等待 go 程执行完,注意睡眠时间不能太短。 } ``` 上述代码中,`once.Do(onceBody)` 确保了 `onceBody` 函数在整个程序生命周期中仅执行一次,即使多个 goroutine 同时调用它 [^5]。这在并发编程中非常有用,可以避免重复执行初始化逻辑。 ### 单例模式实现 `sync.Once` 常用于实现单例模式。例如,一个简单的数据库连接池可以通过 `sync.Once` 来确保仅初始化一次: ```go type Database struct { conn string } var db *Database var once sync.Once func GetDatabaseInstance() *Database { once.Do(func() { db = &Database{conn: "connected"} fmt.Println("Database instance created") }) return db } func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(i int) { defer wg.Done() instance := GetDatabaseInstance() fmt.Printf("Instance %d: %v\n", i, instance) }(i) } wg.Wait() } ``` 在上述代码中,`GetDatabaseInstance()` 函数确保了 `db` 仅被初始化一次,无论多少个 goroutine 调用它 [^1]。 ### 最佳实践 - **避免在 `once.Do()` 中执行耗时操作**:虽然 `once.Do()` 保证了函数仅执行一次,但如果其中的操作非常耗时,可能会导致其他 goroutine 阻塞等待。 - **使用 `sync.Once` 替代全局锁**:当只需要确保某个操作执行一次时,使用 `sync.Once` 比全局锁更高效。 - **适用于初始化逻辑**:`sync.Once` 是初始化配置、连接池、资源加载等场景的理想选择 [^2]。 ### 与 `init` 函数的比较 `sync.Once` 的作用与 `init` 函数类似,但它们的使用时机不同: - `init` 函数在包首次被加载时执行,且只执行一次。 - `sync.Once` 在代码运行期间需要时执行,且只执行一次 [^3]。 因此,如果初始化逻辑依赖于运行时条件或需要延迟加载,`sync.Once` 是更合适的选择。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值