歡迎關注go語言微信公眾號 每日go語言 golang_everyday
sync.once可以控制函數只能被調用一次。不能多次重復調用。示例代碼:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
o := &sync.Once{}
go do(o)
go do(o)
time.Sleep(time.Second * 2)
}
func do(o *sync.Once) {
fmt.Println("Start do")
o.Do(func() {
fmt.Println("Doing something...")
})
fmt.Println("Do end")
}
輸出結果:
Start do
Doing something...
Do end
Start do
Do end
這里 Doing something 只被調用了一次。
查看go once的源碼實現,也是非常的簡單:
type Once struct {
m Mutex
done uint32
}
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
核心思想是使用原子計數記錄被執行的次數。使用Mutex Lock Unlock鎖定被執行函數,防止被重復執行。