我应该避免在golang中打包单身人士吗?

时间:2014-07-05 06:08:18

标签: go singleton global-variables

目前我有一个包store,内容如下:

package store

var (
    db *Database
)

func Open(url string) error {
    // open db connection
}

func FindAll(model interface{}) error {
    // return all entries
}

func Close() {
    // close db connection
}

这使我可以在store.FindAll完成store.Open之后使用其他软件包中的main.go

然而,正如我所看到的那样,大多数软件包都倾向于提供一个需要自己初始化的结构。使用这种全局方法的情况很少。

这种方法的缺点是什么?我应该避免吗?

2 个答案:

答案 0 :(得分:3)

  1. 您无法一次实例化与2个存储的连接。
  2. 使用gomock等方便的工具,您无法在依赖代码的单元测试中轻松模拟存储。

答案 1 :(得分:3)

标准http包有一个ServerMux用于通用用例,但为方便起见,还有一个名为ServerMux http://golang.org/pkg/net/http/#pkg-variablesDefaultServerMux默认实例。因此,当您调用http.HandleFunc时,它会在默认的多路复用器上创建处理程序。您可以找到log和许多其他包中使用的相同方法。这基本上是你的“单身”方式。

但是,我不认为在您的用例中遵循该模式是个好主意,因为无论默认数据库如何,用户都需要调用Open。而且,正因为如此,使用默认实例并没有真正帮助,反而实际上会使它不那么方便:

d := store.Open(...)
defer d.Close()
d.FindAll(...)
写作和阅读比

更容易。

store.Open(...)
defer store.Close()
store.FindAll(...)

而且,还存在语义问题:如果有人两次调用Open会发生什么:

store.Open(...)
defer store.Close()
...
store.Open(...)
store.FindAll(...) // Which db is this referring to?