此刻,我尝试使用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))
}
我的路由器:
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也对访问Go程序中的数据库池的方法也有excellent blog post。
我唯一可以提供的严格建议是,您应该避免在请求上下文中传递数据库池,这效率低下,也不是很好的做法(请求上下文是针对临时的,按请求的对象)。
您始终可以将“ env”定义为global variable。