Go 实现单例模式

551 阅读1分钟

首先创建一个单例类:这个类只能被实例化一次

// 下面是一个单例类
type Singleton struct{   
    name string
}

然后声明一个Singleton类的指针,作为唯一实例的指针

var singleton *Singleton

写出这个单例类的创建方法,因为要保证整个程序只执行一次,不管是单线程下执行多次,还是多线程下多次创建,都只能有一份结构体的实例;使用sync包下的once。

这里顺便说一下once, once接口中传入一个方法,这个方法保证在整个程序运行期间只执行一次。

var once sync.Once
func GetSingleton(name string) *Singleton {   
    once.Do(func() {      
        singleton = &Singleton{name:name}   
    })   
    return singleton
}

我们来测试一下这个单例实现,我们开启10个协程来调用GetSingleton方法,并且在主线程也调用,调用过程中,10个协程包括主线程都传入不同的名字,最后包括主线程在内的11个线程都去打印得到的singleton,看看是不是同一个:

func main() {   
    var wg sync.WaitGroup  
    wg.Add(10)   
    for i:=0; i<10; i++ {      
        go func(name string) {         
            s := GetSingleton(name)         
            fmt.Printf("%v\n", s)        
            wg.Done()      
        }(strconv.Itoa(i))   
    }   
    wg.Wait()   
    s := GetSingleton("main")   
    fmt.Printf("%v\n", s)
}

输出测试结果:

&{0}
&{0}
&{0}
&{0}
&{0}
&{0}
&{0}
&{0}
&{0}
&{0}
&{0}

证明是第一个协程实例化了单例类后,后面的协程都没有进行实例化。