使用mux Router - 如何将我的DB传递给我的处理程序

时间:2015-11-11 08:46:43

标签: go router 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?我尝试了很多东西,但没有一个能奏效。

2 个答案:

答案 0 :(得分:19)

您有三种选择:

  1. 使您的数据库连接池成为全局数据库,这样您就不必传递它。 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.
    }
    
  2. 将处理程序包装在一个闭包中,使内部处理程序可以访问它。你需要根据你的路线范围进行调整 - 这是一个有点迟钝的IMO,并且更难以看到存在哪些路线,但我离题了 - 例如:

    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.
    }
    
  3. 创建一个接受处理程序的自定义处理程序类型 - 例如

    var elms = document.getElementsByClassName("test");
    var n = elms.length;
    
    function changeColor(color) {
        for(var i = 0; i < n; i ++) {
            elms[i].style.backgroundColor = color;
        } 
    }
    for(var i = 0; i < n; i ++) {
        elms[i].onmouseover = function() {
           changeColor("red");
        };
        elms[i].onmouseout = function() {
           changeColor("white");
        };
    }
    
  4. 请注意(无耻的插件!)我written about the last approach in detail,而且Alex Edwards也有excellent blog post方法来访问Go程序中的数据库池。

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

答案 1 :(得分:0)

你总是可以拥有&#34; env&#34;定义为global variable

但是在每个人都恨我之前,这不是一个好的解决方案!您应该使用公共函数创建一个封装对数据库的访问的包,该函数说明您的确切意图。

的内容
<?php
$mydir = "G:\ ";

echo file_exists($mydir) ? "G is mounted":"G is not mounted";
?>

并从您的路由器功能

访问它
Package db

var config ....

func ShowTodos(params ... ) result {
   your database access code here.... 
}