背景

单例模式可以说是最简单的设计模式之一了,功能很简单:一个类型的东西只实例化一次,全局只有一个实例,并提供方法来获取该实例。

initinit

不过本文主要想讨论的单例模式是第一次需要用到时才去初始化,也就是延迟初始化。

不太好的单例实现

svcMu.Lock()if svc == nil svcsvcnilsvc

因为在缺乏显式同步的情况下,编译器和CPU在能保证每个 goroutine 内满足串行一致性的基础上可以自由地重排访问内存的指令顺序。

svc = &Svc{Num: 1}
nil

比较好的单例实现

sync.OnceDoDoif svc == nil sync.Once
sync.Onceatomic.LoadUint32(&o.done) == 0
o.done01f()defer atomic.StoreUint32(&o.done, 1)o.done1o.done0
sync.Onceif svc == nil sync.Once

额外推荐

实则开发中用到的设计模式经常不止一种,越是复杂大型的项目就越需要使用更多合适的模式来优化代码。

下面要推荐的是RefactoringGuru。这是我所见过最好的设计模式教程,是国外创建的一个教程网站,有中文站点,图文并茂地介绍每一种模式的结构、关系和逻辑, 最重要的是示例代码方面囊括了常见的几种主流编程语言,是个适合多数程序员学习设计模式的好地方!

下图是设计模式的目录页面(是不是很图文并茂呢):

https://data.waacoo.cc/upic/program_patten.1600.jpg

结语

以上为本人学习和实践的一些总结,如有错漏还请不吝赐教。

参考

《Go程序设计语言》9.5 延迟初始化:sync.Once 网络版 Go 单例模式讲解和代码示例