如何在多个包之间共享单个数据库连接

时间:2018-02-27 05:37:52

标签: go

我有两个名为client和worker的包。我想与这两个包共享相同的ssdb,mysql和redis连接。 我面临的另一个类似问题是在这两个软件包之间共享auth。

app
  -> client pkg
  -> worker pkg
  main.go (contains auth as global variable)

有人可以建议我实施这两件事的最佳方式吗?

1 个答案:

答案 0 :(得分:1)

对于新的Go开发人员而言,这种方法并不总是显而易见的,实施但不是很糟糕 复杂,通常在初学者应用程序中运行良好:

app
    client // imports storage
    worker // imports storage
    config // all environment-related config goes here
    storage   // storage-engine-generic interface to the packages below it
        ssdb  // all ssdb-specific code here
        mysql // all mysql-specific code here
        redis // ditto

它使用包变量。如果您对导出的包变量的意外写入感到偏执,则可以通过使用未导出的包变量来避免此问题。利用这个 Go中导出标识符的有限定义(参见language specification)。

main,请致电

config.Init(configfile)
storage.Init()

定义config.Init函数以读取配置文件并将包变量设置为您的连接信息 数据库。如果您正在使用enexported包变量,则允许通过导出的函数进行公共只读访问。否则,您可以跳过这些功能,具体取决于您想要的其他功能。

storage中,您的Init函数调用

ssdb.Init()
mysql.Init()
redis.Init()

然后,在storage中,您还有clientserver使用的公共功能,这些功能并非特定于存储引擎,例如

func GetImage(id string) ([]byte) {
    return mysql.GetImage(id)
}

或适用于您的申请的任何内容。 storage抽象级别可能对您有所帮助,也可能不值得,具体取决于您将来如何更改应用程序。你决定是否值得投资。

mysql包中,您导入config,并且您有类似

的内容
var db *sql.DB
func Init() {
    getDb()
}
func getDb() (*sql.DB) {
    if db == nil {  // or something
        config.Log.Println("Opening db connection to mysql")
        db, err := sql.Open("mysql", config.MysqlConnectionString())
        // do something with err, possibly have a retry loop
    }
    return db
}
func GetImage(id string) ([]byte)
     db := getDb()
     // ...

mysql包中的函数可以使用db未导出的包变量,但其他包不能。

将未导出的包变量与导出函数只读访问一起使用并不是一种糟糕的做法,也不是特别复杂。也就是说,它通常是不必要的。如果db是导出的包变量Db,您是否会突然输入

mysql.Db, _ = sql.Open("mysql", "LEEERRROOYYYYY!!!!")

在您的client代码中(并决定导入mysqlsql来执行此操作)然后部署到生产环境中?为什么你更有可能这样做而不是故意破坏代码的任何其他部分?

请注意,如果您只是输入

mysql.Db = "LEEERRROOYYYYYY!!!!"

由于类型不匹配,您的应用程序将无法编译。