Go 使用mux路由器-如何将我的DB传递给我的处理程序

Go 使用mux路由器-如何将我的DB传递给我的处理程序,go,router,mux,Go,Router,Mux,目前,我尝试使用Go在服务器上进行数据处理来创建一个小型Web项目 我试图将数据库连接传递给HandlerFunc,但它没有按预期工作。我是刚来戈兰的新手,所以我可能不了解这个语言的一些基本原理 我的主要功能如下所示: func main() { db, err := config.NewDB("username:password@/databasename?charset=utf8&parseTime=True") if err != nil { lo

目前,我尝试使用Go在服务器上进行数据处理来创建一个小型Web项目

我试图将数据库连接传递给HandlerFunc,但它没有按预期工作。我是刚来戈兰的新手,所以我可能不了解这个语言的一些基本原理

我的主要功能如下所示:

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)传递给我的funcHandler呢?我尝试了很多东西,但都不管用

您始终可以将“env”定义为

但在所有人都恨我之前,这不是一个好的解决办法!您应该创建一个包,用公共函数封装对数据库的访问,该函数声明您的确切意图

类似于

Package db

var config ....

func ShowTodos(params ... ) result {
   your database access code here.... 
}
并通过路由器功能访问它

db.ShowTodos(...)

您有三种选择:

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

    var db *sql.DB
    
    func main() {
        var err error
        db, err = sql.Open(...)
        // Now accessible globally, no need to pass it around
        // ...
     }
    
  • 将处理程序包装在闭包中,这样内部处理程序就可以访问它。你需要根据你的“路线范围”方法进行调整,这在我看来有点迟钝,使你更难看到存在哪些路线,但我离题了,例如:

    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程序中DB池的方法


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

    非常感谢,我已经看过Alex Edwards blogpost,并尝试实现他的关闭解决方案(使用他在的示例)现在,我更改了它,并在我的模型包中使用了一个全局变量,它正在工作。我仍然不确定它是否是我的项目的最佳解决方案,但目前它将适合我的需要。谢谢你!刚刚开始与Golang和GORM一起使用,并且已经搜索了大约一个小时的“正确”选项让我的db对象进入我的处理程序以便它们可以访问数据库的方法。