我有两个名为client和worker的包。我想与这两个包共享相同的ssdb,mysql和redis连接。 我面临的另一个类似问题是在这两个软件包之间共享auth。
app
-> client pkg
-> worker pkg
main.go (contains auth as global variable)
有人可以建议我实施这两件事的最佳方式吗?
答案 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
中,您还有client
和server
使用的公共功能,这些功能并非特定于存储引擎,例如
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
代码中(并决定导入mysql
和sql
来执行此操作)然后部署到生产环境中?为什么你更有可能这样做而不是故意破坏代码的任何其他部分?
请注意,如果您只是输入
mysql.Db = "LEEERRROOYYYYYY!!!!"
由于类型不匹配,您的应用程序将无法编译。