Singleton in go
如何在Go编程语言中实现单例设计模式?
抛开实现singleton模式是否是一个好主意的争论,下面是一个可能的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package singleton type single struct { O interface{}; } var instantiated *single = nil func New() *single { if instantiated == nil { instantiated = new(single); } return instantiated; } |
然而,正如其他一些人所指出的,这不是线程安全的,除非您只是在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package singleton import"sync" type single struct { O interface{}; } var instantiated *single var once sync.Once func New() *single { once.Do(func() { instantiated = &single{} }) return instantiated } |
另见,哈桑J的建议只是把一个包裹当作一个单件。最后,要考虑其他人的建议:单例常常是一个有问题的实现的指示器。
在试图找到一种方法屈从于你的意志之前,你可能需要看一些文章:
单打-反模式!
单身是病态的骗子
单子现象的根本原因。
总的来说,随着时间的推移,人们发现单例开发并不是最理想的,而且imho尤其是当你尝试进行任何测试驱动的开发时:在许多层面上,它们和全局变量一样糟糕。
[免责声明:我知道这不是对您问题的严格回答,但它确实是相关的]
只需将变量和函数放在包级别。
另请参见类似的问题:如何在Python中生成单例
我认为,在一个并发的世界中,我们需要更清楚地认识到这些行不是原子地执行的:
1 2 3 | if instantiated == nil { instantiated = new(single); } |
我会按照@markermer的建议使用"同步"软件包。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import"sync" type MySingleton struct { } var _init_ctx sync.Once var _instance *MySingleton func New() * MySingleton { _init_ctx.Do( func () { _instance = new(MySingleton) } ) return _instance } |
最好的方法是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package singleton import"sync" type singleton struct { } var instance *singleton var once sync.Once func GetInstance() *singleton { once.Do(func() { instance = &singleton{} }) return instance } |
你应该阅读这个链接
您可以使用ONCE包进行初始化:
这将确保只调用一次init方法。
您应该知道,
来自https://golang.org/pkg/sync/once.do
If f (note: the once logic) panics, Do considers it to have returned; future calls of Do return without calling f.
我使用互斥来确保全局配置变量的唯一初始化,以克服此限制:
- https://golang.org/pkg/sync/互斥
- https://gobyexample.com/mutex
只需要一个静态的、最终的、常量的、全局的、应用程序范围的对象实例。
然而,这与OO范式相矛盾。它的使用应该局限于原语和不变的对象,而不是可变的对象。