# 单例模式

> 此开源图书由[ithaiq](https://github.com/ithaiq)原创，创作不易转载请注明出处

* 第一个版本

```go
type Config struct{}

var config *Config

func GetConfig() *Config {
    if config != nil {
        config = &Config{}
    }
    return config
}
```

第一个版本在多协程执行会产生线程不安全的问题，改进如下第二个版本

```go
type Config struct{}

var config *Config
var mu sync.Mutex

func GetConfig() *Config {
    if config != nil {
        mu.Lock()
        defer mu.Unlock()
        config = &Config{}
    }
    return config
}
```

第二个版本虽然解决线程不安全问题但是多个协程并发调用可能获取"中间状态"的数据，改进后第三个版本

```go
type Config struct{}

var config *Config
var mu sync.Mutex
var isSet uint32

func GetConfig() *Config {
    if atomic.LoadUint32(&isSet) == 1 {
        return config
    }
    mu.Lock()
    defer mu.Unlock()
    if isSet == 0 {
        config = &Config{}
        atomic.StoreUint32(&isSet,1)
    }
    return config
}
```

第三个版本虽然能解决线程不安全问题但是每次加锁性能有影响，改进后第四个版本

```go
type Config struct{}

var config *Config
var once sync.Once

func GetConfig() *Config {
    once.Do(func() {
        config = &Config{}
    })
    return config
}
```

综合分析：第四个版本性能最好，因为只会执行一次所以只有一次加锁的开销
