场景
典型应用场景就是执行仅需执行一次的任务。例如,数据库连接池的初始化任务。又例如,一些心跳检测之类的实时监测任务。等等。
知识点
- 拥有一个 Do 的方法,该类型的方法Do可以接受一个无参数、无结果的函数值作为其参数。该方法一旦被调用,就会调用被作为参数传入的那个函数。且该方法只会运行一次。
- 内部通过 Mutex 和 atomic 实现线程安全。
栗子
1. 普通使用
func main() {var once sync.Onceonce.Do(func() { fmt.Println("Once!") })once.Do(func() { fmt.Println("Once!") })fmt.Println("run ok")}结果:Once!run ok
2. 单例模式
//Singleton 是单例模式类type Singleton struct{}var singleton *Singletonvar once sync.Once//GetInstance 用于获取单例模式对象func GetInstance() *Singleton {once.Do(func() {singleton = &Singleton{}})return singleton}
const parCount = 100func TestSingleton(t *testing.T) {ins1 := GetInstance()ins2 := GetInstance()if ins1 != ins2 {t.Fatal("instance is not equal")}}func TestParallelSingleton(t *testing.T) {wg := sync.WaitGroup{}wg.Add(parCount)instances := [parCount]*Singleton{}for i := 0; i < parCount; i++ {go func(index int) {instances[index] = GetInstance()wg.Done()}(i)}wg.Wait()for i := 1; i < parCount; i++ {if instances[i] != instances[i-1] {t.Fatal("instance is not equal")}}}
