为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
白衣染霜花 2021-11-22 15:31:35
目前,我尝试使用 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 []Routevar routes = Routes{    Route{        "Index",        "GET",        "/",        controller.Index,    },      Route{        "Show",        "GET",        "/todos/{todoId}",        controller.TodoShow,    },      Route{        "Create",        "POST",        "/todos",        controller.TodoCreate,    },  }那么 - 如何将我的“env”(或 env.DB)传递给我的 FuncHandlers?我尝试了很多东西,但没有一个奏效。
查看完整描述

2 回答

?
守候你守候我

TA贡献1802条经验 获得超10个赞

您有三个选择:


使您的数据库连接池成为全局的,这样您就不必传递它。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.

}

请注意(无耻的插件!)我已经详细描述了最后一种方法,Alex Edwards 也有一篇关于在 Go 程序中访问数据库池的方法的优秀博客文章。


我可以给出的唯一严格建议是,您应该避免在请求上下文中传递数据库池,这是低效且不好的做法(请求上下文用于临时的、每个请求的对象)。


查看完整回答
反对 回复 2021-11-22
?
慕斯709654

TA贡献1840条经验 获得超5个赞

您始终可以将“env”定义为全局变量。


但在大家讨厌我之前,这可不是什么好办法!您应该创建一个包,该包使用公共函数来封装对数据库的访问,以说明您的确切意图。


类似的东西


Package db


var config ....


func ShowTodos(params ... ) result {

   your database access code here.... 

}

并从您的路由器功能访问它


db.ShowTodos(...)


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信