github.com/songzhibin97/gkit@v1.2.13/sys/once/once.go (about)

     1  package once
     2  
     3  import (
     4  	"sync"
     5  	"sync/atomic"
     6  )
     7  
     8  // Once 更强大的Once实现
     9  // 在调用 f 失败的时候不会设置 done 并且可以返回失败信息
    10  // 在失败的情况下也可以继续调用 Once 重试
    11  type Once struct {
    12  	m    sync.Mutex
    13  	done uint32
    14  }
    15  
    16  // Do 传入的函数f有返回值error,如果初始化失败,需要返回失败的error
    17  // Do方法会把这个error返回给调用者
    18  func (o *Once) Do(f func() error) error {
    19  	if atomic.LoadUint32(&o.done) == 1 { // fast path
    20  		return nil
    21  	}
    22  	return o.slowDo(f)
    23  }
    24  
    25  // 如果还没有初始化
    26  func (o *Once) slowDo(f func() error) error {
    27  	o.m.Lock()
    28  	defer o.m.Unlock()
    29  	var err error
    30  	if o.done == 0 { // 双检查,还没有初始化
    31  		err = f()
    32  		if err == nil { // 初始化成功才将标记置为已初始化
    33  			atomic.StoreUint32(&o.done, 1)
    34  		}
    35  	}
    36  	return err
    37  }