Once

Once 能够用来执行且仅仅执行一次动作,经常用于单例对象的初始化场景。

once可用于实现单例模式中懒汉实现:

package mainimport (    "fmt"    "sync")var once sync.Oncetype single struct {}var singleInstance *singlefunc 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}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()}

Once构造体

type Once struct {    done uint32        // done 批示操作是否已执行    m    Mutex}

Do

func (o *Once) Do(f func())

sync.Once 只裸露了一个办法 Do,你能够屡次调用 Do 办法,然而只有第一次调用 Do
办法时 f 参数才会执行,这里的 f 是一个无参数无返回值的函数。因为当且仅当第一次调用 Do 办法的时候参数 f 才会执行,即便第二次、第三次、第 n 次调用时 f 参数的值不一样,也不会被执行。

func (o *Once) Do(f func()) {    if atomic.LoadUint32(&o.done) == 0 {        // Outlined slow-path to allow inlining of the fast-path.        o.doSlow(f)    }}func (o *Once) doSlow(f func()) {    o.m.Lock()    defer o.m.Unlock()    // 双重检测    // 保障了并发的 goroutine 会期待 f 实现,而且还不会屡次执行 f。    if o.done == 0 {        defer atomic.StoreUint32(&o.done, 1)        f()    }}