Go using mux Router - 如何将我的数据库传递给我的处理程序

标签 go router mux

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

最佳答案

你有三个选择:

  1. 使您的数据库连接池成为全局连接池,这样您就不必传递它。 sql.DB 对于并发访问是安全的,这是最简单的方法。缺点是它使测试更加困难并且混淆了池来自“哪里” - 例如

    var db *sql.DB
    
    func main() {
        var err error
        db, err = sql.Open(...)
        // Now accessible globally, no need to pass it around
        // ...
     }
    
  2. 将您的处理程序包裹在一个闭包中,使其可供内部处理程序访问。您需要根据您的路线范围方法调整此方法——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.
    }
    
  3. 创建接受处理程序的自定义处理程序类型 - 例如

    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/

相关文章:

multithreading - 半异步代码逻辑

由 C 数组支持的 slice

go - 具有独立处理程序的 PathPrefixed 子路由器

go - 使用 go 递归地提供静态文件

go - 如何检索选中的值

Backbone.js —触发路由之前/之后的调用方法

ios - 如何在 Objective-C 中找到路由器 IP 地址?

node.js - ExpressJS 应用程序未为嵌套路由提供正确的公共(public)文件

postgresql - 使用嵌套对象(结构)在 Go API 中插入数据

json - Go 中的嵌套 JSON 反序列化