Go 中的单例
如何在Go语言中实现单例设计模式?
How does one implement the Singleton design pattern in the go programming language?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如何在Go语言中实现单例设计模式?
How does one implement the Singleton design pattern in the go programming language?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(10)
抛开实现单例模式是否是个好主意的争论,这里有一个可能的实现:
single
和instantiated
是私有的,但New()< /code> 是公开的。因此,您无法在不通过
New()
的情况下直接实例化single
,并且它会使用私有布尔值instantiated
来跟踪实例化的数量。根据喜好调整single
的定义。然而,正如其他几个人指出的,这不是线程安全的,除非您仅在
init()
中初始化您的单例。更好的方法是利用sync.Once
来为您完成艰苦的工作:另请参阅 hasan j 的建议,即仅将包视为单例。最后,请考虑其他人的建议:单例通常是有问题的实现的指标。
Setting aside the argument of whether or not implementing the singleton pattern is a good idea, here's a possible implementation:
single
andinstantiated
are private, butNew()
is public. Thus, you can't directly instantiatesingle
without going throughNew()
, and it tracks the number of instantiations with the private booleaninstantiated
. Adjust the definition ofsingle
to taste.However, as several others have noted, this is not thread-safe, unless you're only initializing your singleton in
init()
. A better approach would be to leveragesync.Once
to do the hard work for you:See also, hasan j's suggestion of just thinking of a package as a singleton. And finally, do consider what others are suggesting: that singletons are often an indicator of a problematic implementation.
最好的方法是:
您应该阅读此链接
The best approach will be:
You should read this Link
只需将变量和函数放在包级别即可。
另请参阅类似的问题:How to make a singleton in Python
Just put your variables and functions at the package level.
Also see similar question: How to make a singleton in Python
我认为在并发世界中,我们需要更加意识到这些行不是自动执行的:
我会遵循@marketer的建议并使用包“sync”
I think that in a concurrent world we need to be a bit more aware that these lines are not executed atomically:
I would follow the suggestion of @marketer and use the package "sync"
在尝试找到一种方法来屈服于你的意愿之前,你可能需要看看一些文章:
SINGLETON - 反模式!
单身人士都是病态的骗子
单例的根本原因。
总之,随着时间的推移,人们发现单例并不是最佳的,恕我直言,尤其是如果您尝试进行任何测试驱动的开发:在许多层面上,它们几乎与全局变量一样糟糕。
[免责声明:我知道这不是对你的问题的严格回答,但它确实相关]
Before trying to find a way to bend Go to your will, you might want to take a look at some articles:
SINGLETON - the anti-pattern!
Singletons are Pathological Liars
Root Cause of Singletons.
In summary, over time people have found singletons to be less than optimal, and imho especially if you are trying to do any test-driven development: on many levels they are pretty much as bad as global variables.
[disclaimer: I know its not a strict answer to your question but it really is relevant]
正如您在以下代码中看到的那样,很简单:
预期结果是:
因为您正在访问相同的资源。这就是我添加互斥锁的原因,以便能够从多个进程并发访问 count 属性。 :-)
来源:
https://play.golang.org/p/2XnLztX8Gs5
Easy peasy as you can see in the following code:
Expected result would be:
Because you're accessing to the same resource. That's the reason I've added mutex in order to be concurrent proven accessing count attribute from multiple processes. :-)
Source:
https://play.golang.org/p/2XnLztX8Gs5
您可以使用 once 包 进行初始化:
这将确保您的 init 方法仅被调用一次。
You can do initialization using the once package:
This will ensure that your init methods only get called once.
只需拥有所需对象的单个静态、最终、常量、全局、应用程序范围实例即可。
然而,这与面向对象范式相矛盾。它的使用应仅限于基元和不可变对象,而不是可变对象。
Just have a single static, final, constant, global, application-wide instance of the Object you want.
This however contradicts the OO paradigm. Its use should be limited to primitives and immutable objects, not to mutable objects.
您应该知道
Once.Do
非常重视只执行一次代码。这意味着,代码总是只执行一次,即使它可能已经恐慌:来自 https://golang.org/pkg/sync/#Once.Do
我使用互斥体来确保全局配置变量的唯一初始化,以克服此限制:
You should be aware that
Once.Do
is serious about executing the code only once. That means, the code is always executed only once, even though it might have panicked:from https://golang.org/pkg/sync/#Once.Do
I used mutexes instead to ensure unique initialisation of a global configuration variable to overcome this restriction:
我认为如果你想要 Go 中的单例之类的东西,你应该尝试思考你想要实现的目标。与 Java 或 C# 不同,Go 没有“静态”类的概念,因此传统的区别不太明确。在我看来,您希望从单例中获得的关键点是不允许其他人构建它。为此,我认为可以更简单地实现:导出一个接口,实现一个实现该接口的未导出类,然后导出它的单个实例。例如:
正如其他答案所示,有很多更字面的方法可以在 Go 中实现单例模式,但它们让我觉得答案是从必须精确复制模式的前提开始的,而不是从解决实际的问题开始。你在 Go 中遇到的问题。
I think if you want something like a singleton in Go you should try and think about what you're trying to achieve. Unlike Java or C#, Go has no concept of "static" classes, so the traditional distinction is less clear. In my mind, the key point you'd want from a singleton is not allowing others to construct it. To that end, I think it can achieved more simply: export an interface, implement an unexported class which implements this interface, and export a single instance of it. For instance:
As the other answers show, there are many more literal ways you can implement the singleton pattern in Go, but they strike me as answers that start from the premise that the pattern must be copied exactly, rather than starting from solving a real problem you have in Go.