Once 保证操作只执行一次
- 适用于一些单例、配置的加载等
内部数据结构
go
type Once struct {
done atomic.Uint32
m Mutex
}
done
用于标识操作是否已经完成只有0
或1
m
互斥锁
核心方法
-
Do
scssfunc (o *Once) Do(f func()) { if o.done.Load() == 0 { o.doSlow(f) } } func (o *Once) doSlow(f func()) { o.m.Lock() defer o.m.Unlock() if o.done.Load() == 0 { defer o.done.Store(1) f() } }
-
原子加载
done
值是否为0
-
如果等于
0
说明f func()
并没有被初始化 -
进入
doSlow
方法 -
加锁,然后再次原子加载
done
值是否为0
。这里进行可一个double check
,确保当前done
的值没有被修改 -
执行
f func()
,然后将done
标记为1
once这个并发原底层代码非常简洁,也很好理解。