go单例模式之懒汉模式

2020-01-05  本文已影响0人  CaiGuangyin

可以通过sync包中的sync.Once实现单例模式。

var once sync.Once
// 传入方法Do()中的函数只会被执行一次。
once.Do(func(){})

如下是once.go中的Do()方法的源码:

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()
    }
}

下面是用sync.Once实现的单例模式

package main

import (
    `fmt`
    `sync`
)

type Singleton struct {}

var singleton *Singleton
var once sync.Once

func GetSingletonObj() *Singleton {
    once.Do(func() {
        fmt.Println("create singletonObj.")
        singleton = new(Singleton)
    })
    return singleton
}

func main() {
    var wg sync.WaitGroup
    for i:=0;i<10;i++ {
        wg.Add(1)    // 往等待组中添加一个协程
        go func() {
            singleObj := GetSingletonObj()
                        // 打印singleObj的指针
            fmt.Printf("singleObj mem addr: %p\n", singleObj)
            wg.Done()    // 协程执行完毕,会调用`wg.Add(-1)`将计数减1
        }()
    }
    wg.Wait()    // 等待所有协程执行完毕
}

sync.WaitGroup的作用是让主函数main()等待所有协程go func(){}执行完后才退出。

输出的结果如下:

create singletonObj.
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0
singleObj mem addr: 0x5851d0

从输出结果可以看出,create singletonObj只被打印了一次,也就证明传入once.Do()中的函数只被执行了一次,而GetSingletonObj()只在第一次执行时会创建一个singleton,后面每次执行返回的都是同一个singleton,从输出结果的singleObj mem addr就可以看出来。

上一篇下一篇

猜你喜欢

热点阅读