Skip to content

Go 中使用单例模式 #83

@kevinyan815

Description

@kevinyan815

单例模式,分两种加载模式,下面介绍下 Go 里面怎么使用单例模式。

饿汉模式

适合程序初始化时就确定怎么加载实例的情况

package singleton

// Singleton 饿汉式单例
type Singleton struct{}

var singleton *Singleton

func init() {
	singleton = &Singleton{}
}

// GetInstance 获取实例
func GetInstance() *Singleton {
	return singleton
}

懒汉模式

延迟加载,适合根据传入参数实现定制化的初始化操作。

package singleton

import (
	"sync"
	"sync/atomic"
)


type singleton struct {}

var (
	initialized uint32
	instance *singleton
	mu sync.Mutex
)

func GetInstance() *singleton {

	if atomic.LoadUint32(&initialized) == 1 { // 原子操作
		return instance
	}

	mu.Lock()
	defer mu.Unlock()

	if initialized == 0 {
		instance = &singleton{}
		atomic.StoreUint32(&initialized, 1)
	}

	return instance
}

上面通过了atomic 和 mutex 进行双重检查,保证线程安全,不过可以利用 sync.Once 实现更简洁的版本,这一版最好也记住,有可能面试的时候就不让你用sync.Once实现,sync.Once 内部也是维护了个标志为,用atomic 判断它是否已经执行过函数

Java 里的线程安全的单例也是这么通过volatile+synchronized 双锁检查实现的。

简洁版的懒汉模式单例

package singleton

type singleton struct {}

var instance *singleton
var once sync.Once

func GetInstance() *singleton {
	once.Do(func() {
		instance = &singleton{}
	})
	return instance
}

这里直接上的代码,没有什么废话,如果想看故事版的,可以访问最简单的单例模式,Go版本的实现你写对了吗?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions