Go设计模式之Singleton
Overview
Singleton - 单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
实现
饿汉式
饿汉式单例是指在方法调用前,实例就已经创建好了。
按照用法使用,可以看到控制台输出10次单例的内存地址是一样的。
1package main
2
3import (
4 "fmt"
5 "sync"
6 "time"
7)
8
9type (
10 server struct {
11 port int
12 }
13)
14
15var (
16 instance = &server{}
17)
18
19func getServerSingleton() *server {
20 return instance
21}
22
23/*
24server ptr: 0x1182ec0
25server ptr: 0x1182ec0
26server ptr: 0x1182ec0
27server ptr: 0x1182ec0
28server ptr: 0x1182ec0
29server ptr: 0x1182ec0
30server ptr: 0x1182ec0
31server ptr: 0x1182ec0
32server ptr: 0x1182ec0
33server ptr: 0x1182ec0
34*/
懒汉式 - 非Goroutine安全
懒汉式单例是指在方法调用获取实例时才创建实例,因为相对饿汉式显得“不急迫”,所以被叫做“懒汉模式”。
按照用法使用,可以看到控制台输出10次单例的内存地址并不完全一样。
一共有以下3个指针:
- 0xc0000c4000
- 0xc0000ca000
- 0xc0000c2000
可见此懒汉模式不支持在实例未初始化时高并发调用。
1package main
2
3type (
4 server struct {
5 port int
6 }
7)
8
9var (
10 instance *server
11)
12
13func getServerSingleton() *server {
14 if instance == nil {
15 instance = &server{}
16 }
17
18 return instance
19}
20
21/*
22server ptr: 0xc0000c4000
23server ptr: 0xc0000ca000
24server ptr: 0xc0000c4000
25server ptr: 0xc0000c2000
26server ptr: 0xc0000c2000
27server ptr: 0xc0000ca000
28server ptr: 0xc0000ca000
29server ptr: 0xc0000ca000
30server ptr: 0xc0000ca000
31server ptr: 0xc0000ca000
32*/
懒汉式 - Goroutine安全
我们可以利用golang sync包提供的Once结构体来解决Goroutine安全问题。Once提供了在应用程序生命周期中仅会被调用一次的解决方案。我们将实例的生成过程使用Once保护起来,那么即可以做到单例。
1package main
2
3import (
4 "sync"
5)
6
7type (
8 server struct{}
9)
10
11var (
12 instance *server
13 once sync.Once
14)
15
16func getServerSingleton() *server {
17 once.Do(func() {
18 instance = &server{}
19 })
20
21 return instance
22}
23
24/*
25server ptr: 0x1182f88
26server ptr: 0x1182f88
27server ptr: 0x1182f88
28server ptr: 0x1182f88
29server ptr: 0x1182f88
30server ptr: 0x1182f88
31server ptr: 0x1182f88
32server ptr: 0x1182f88
33server ptr: 0x1182f88
34server ptr: 0x1182f88
35*/
用法
模拟10个并发请求获取单例。
1func main() {
2 wg := sync.WaitGroup{}
3
4 for index := 0; index < 10; index++ {
5 wg.Add(1)
6
7 go func() {
8 time.Sleep(time.Millisecond * 100)
9
10 server := getServerSingleton()
11 fmt.Printf("server ptr: %p \n", server)
12
13 wg.Done()
14 }()
15 }
16
17 wg.Wait()
18}