目前,我尝试使用Go在服务器上创建一个小型Web项目进行数据处理.
我尝试将我的数据库连接传递给我的HandlerFunc(tions)但它没有按预期工作.我对golang很新,所以也许我不明白这个lang的一些基本原理.
我的主要功能如下:
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))
}
Run Code Online (Sandbox Code Playgroud)
我的路由器:
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
}
Run Code Online (Sandbox Code Playgroud)
和我的路线:
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,
},
}
Run Code Online (Sandbox Code Playgroud)
那么 - 我怎样才能将我的"env"(或env.DB)传递给我的FuncHandlers?我尝试了很多东西,但没有一个能奏效.
eli*_*rar 20
你有三个选择:
使您的数据库连接池成为全局数据库,这样您就不必传递它.sql.DB对于并发访问是安全的,这是最简单的方法.缺点是它会使测试变得更加困难,并且模糊了池的来源 - 例如
var db *sql.DB
func main() {
var err error
db, err = sql.Open(...)
// Now accessible globally, no need to pass it around
// ...
}
Run Code Online (Sandbox Code Playgroud)将处理程序包裹在一个闭包中,使内部处理程序可以访问它.你需要将它调整到你的路线覆盖范围 - 这是一个有点迟钝的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.
}
Run Code Online (Sandbox Code Playgroud)创建一个接受处理程序的自定义处理程序类型 - 例如
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.
}
Run Code Online (Sandbox Code Playgroud)请注意(无耻的插件!)我已经详细介绍了最后一种方法,Alex Edwards也有关于访问Go程序中数据库池的方法的优秀博客文章.
我可以给出的唯一严格的建议是,你应该避免在请求上下文中传递你的数据库池,这是低效的而不是好的做法(请求上下文是临时的,每个请求对象).