目前,我尝试使用 Go 创建一个小型 Web 项目以在服务器上处理数据。
我尝试将我的数据库连接传递给我的 HandlerFunc(tions),但它没有按预期工作。我是 golang 的新手,所以可能我不了解这个语言的一些基本原理。
我的主要功能是这样的:
func main() {
db, err := config.NewDB("username:password@/databasename?charset=utf8&parseTime=True")
if err != nil {
log.Panic(err)
}
env := &config.Env{DB: db}
router := NewRouter(env)
log.Fatal(http.ListenAndServe(":8080", router))
}
我的路由器:
func NewRouter(env *config.Env) *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
var handler http.Handler
handler = route.HandlerFunc
handler = Logger(handler, route.Name)
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(handler)
}
return router
}
和我的路线:
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
var routes = Routes{
Route{
"Index",
"GET",
"/",
controller.Index,
},
Route{
"Show",
"GET",
"/todos/{todoId}",
controller.TodoShow,
},
Route{
"Create",
"POST",
"/todos",
controller.TodoCreate,
},
}
那么 - 如何将我的“env”(或 env.DB)传递给我的 FuncHandlers?我尝试了很多东西,但都没有用。
最佳答案
你有三个选择:
使您的数据库连接池成为全局连接池,这样您就不必传递它。
sql.DB
对于并发访问是安全的,这是最简单的方法。缺点是它使测试更加困难并且混淆了池来自“哪里” - 例如var db *sql.DB func main() { var err error db, err = sql.Open(...) // Now accessible globally, no need to pass it around // ... }
将您的处理程序包裹在一个闭包中,使其可供内部处理程序访问。您需要根据您的路线范围方法调整此方法——IMO 有点迟钝,并且更难看到存在哪些路线,但我离题了——例如:
func SomeHandler(db *sql.DB) http.HandlerFunc { fn := func(w http.ResponseWriter, r *http.Request) { res, err := db.GetThings() // etc. } return http.HandlerFunc(fn) } func main() { db, err := sql.Open(...) http.HandleFunc("/some-route", SomeHandler(db)) // etc. }
创建接受处理程序的自定义处理程序类型 - 例如
type AppHandler struct { Handler func(env *config.Env, w http.ResponseWriter, r *http.Request) Env *config.Env } // ServeHTTP allows your type to satisfy the http.Handler interface. func (ah *AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { ah.Handler(ah.Env, w, r) } func SomeHandler(env *config.Env, w http.ResponseWriter, r *http.Request) { res, err := env.DB.GetThings() // etc. }
请注意(无耻的插件!)我有 written about the last approach in detail , Alex Edwards 有一个 excellent blog post关于在 Go 程序中访问数据库池的方法。
我能给出的唯一严格建议是,你应该避免在请求上下文中传递你的数据库池,这是低效的,也不是好的做法(请求上下文是针对临时的、按请求的对象)。
关于Go using mux Router - 如何将我的数据库传递给我的处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33646948/