使用 mux 路由器 - 如何将我的数据库传递给我的处理程序

目前,我尝试使用 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?我尝试了很多东西,但没有一个奏效。


白衣染霜花
浏览 164回答 2
2回答

守候你守候我

您有三个选择:使您的数据库连接池成为全局的,这样您就不必传递它。sql.DB对于并发访问是安全的,这是最简单的方法。缺点是它使测试变得更加困难并且混淆了池的“来源”——例如var db *sql.DBfunc 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.}请注意(无耻的插件!)我已经详细描述了最后一种方法,Alex Edwards 也有一篇关于在 Go 程序中访问数据库池的方法的优秀博客文章。我可以给出的唯一严格建议是,您应该避免在请求上下文中传递数据库池,这是低效且不好的做法(请求上下文用于临时的、每个请求的对象)。

慕斯709654

您始终可以将“env”定义为全局变量。但在大家讨厌我之前,这可不是什么好办法!您应该创建一个包,该包使用公共函数来封装对数据库的访问,以说明您的确切意图。类似的东西Package dbvar config ....func ShowTodos(params ... ) result {   your database access code here.... }并从您的路由器功能访问它db.ShowTodos(...)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go