我已经阅读了一些关于如何处理数据库连接的StackOverflow答案.由于它是一个池,我们可以在全局定义它并在多个goroutine中使用它并且它是安全的.
我遇到的问题是我已将REST API拆分为多个包.这些包中的每一个都需要数据库连接,因此我在启动时打开数据库连接.但即使我全局定义连接,它也只是在包级别.我可以做些什么来在多个包中分享它?
对于某些上下文,我在我的应用程序中使用PostgreSQL驱动程序和gin-gonic.
Maa*_*aaz 77
还可以选择创建另一个包来保存与数据库连接相关的设置.然后它可以具有全局包级别,可以main在任何导入它的包中初始化并使用它.
这样,您可以明确地看到正在导入数据库包.这是一些示例代码.
package database
var (
// DBCon is the connection handle
// for the database
DBCon *sql.DB
)
Run Code Online (Sandbox Code Playgroud)
package main
import "myApp/database"
func main() {
var err error
database.DBCon, err = sql.Open("postgres", "user=myname dbname=dbname sslmode=disable")
}
Run Code Online (Sandbox Code Playgroud)
package user
import "myApp/database"
func Index() {
// database handle is available here
database.DBCon
...
}
Run Code Online (Sandbox Code Playgroud)
eli*_*rar 11
简单的答案:将初始化的连接池传递给包的自己的全局变量.
例如
// package stuff
var DB *sql.DB
func GetAllStuff() (*Stuff, error) {
err := DB.Query("...")
// etc.
}
// package things
var DB *sql.DB
func GetAllThings() (*Thing, error) {
err := DB.Query("...")
// etc.
}
// package main
func main() {
db, err := sql.Open("...")
if err != nil {
log.Fatal(err)
}
stuff.DB = db
things.DB = db
// etc.
}
Run Code Online (Sandbox Code Playgroud)
我们定义包级别的全局变量,确保它们被导出(大写),然后将指针传递给它们的连接池.
这是"好的",但可以屏蔽"使用"的东西.如果你正在寻找一个处理程序可能并不清楚其中的连接是从哪里来的,尤其是你的包增长.更具伸缩性的方法可能如下所示:
// package stuff
type DB struct {
*sql.DB
}
func New(db *sql.DB) (*DB, error) {
// Configure any package-level settings
return &DB{db}, nil
}
func (db *DB) GetAllStuff() (*Stuff, error) {
err := db.Query("...")
// etc.
}
// package things
type DB struct {
*sql.DB
}
func New(db *sql.DB) (*DB, error) {
// Configure any package-level settings
return &DB{db}, nil
}
func (db *DB) GetAllThings() (*Thing, error) {
err := db.Query("...")
// etc.
}
// package main
func main() {
db, err := sql.Open("...")
if err != nil {
log.Fatal(err)
}
stuffDB, err := stuff.New(db)
if err != nil {
log.Fatal(err)
}
thingsDB, err := things.New(db)
if err != nil {
log.Fatal(err)
}
// Simplified.
http.HandleFunc("/stuff/all", stuff.ShowStuffHandler(stuffDB))
http.HandleFunc("/things/all", things.ShowThingsHandler(thingsDB))
// etc.
}
func ShowStuffHandler(db *stuff.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// We can use our stuff.DB here
stuff, err := db.GetAllStuff()
// etc.
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不仅仅将数据库连接作为依赖项(例如config params,hostnames等),请将它们包装在每个包的things.Envstruct或stuff.Envstruct中.
一个例子是有一个things.New("deps...") *Env函数返回一个*things.Env包含你的things包使用的依赖项的配置.