去使用mux路由器 - 如何将我的数据库传递给我的处理程序 [英] Go using mux Router - How to pass my DB to my handlers

查看:121
本文介绍了去使用mux路由器 - 如何将我的数据库传递给我的处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我尝试将我的数据库连接传递给我HandlerFunc(tions),但它不能按预期工作。我对golang很新,所以也许我不明白这个lang的一些基本原则。



我的主要功能如下所示:

  func main(){

db,err:= config.NewDB(username:password @ / databasename?charset = utf8&如果err!= nil {
log.Panic(err)
}
env:=& config.Env {DB:db}


router:= NewRouter(env)
log.Fatal(http.ListenAndServe(:8080,router))
}
pre>

我的路由器:

  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。
方法(route.Method)。
路径(route.pattern)。
名称(route.Name)。
处理程序

返回路由

$ c $ $ $ $ $

和我的路线:

 类型路径结构{
名称字符串
方法字符串
模式字符串
HandlerFunc http.HandlerFunc
}

类型路由[]路由

var routes =路由{
路由{
Index,
GET,
/,
controller.Index,
},
Route {
Show,
GET,
/ todos / {todoId},
controller.TodoShow,
},
路由{
Create,
POST,
/ todos,
controller.TodoCreate,
},
}

那么 - 如何将我的env(或env.DB)传递给我的FuncHandlers?我尝试了很多东西,但都没有工作。

解决方案

您有三个选择:
$ b $ ol <

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

      var db * sql.DB 

    func main(){
    var err error
    db,err = sql.Open(...)
    //现在可以全局访问,不需要传递它约
    // ...
    }


  • 一个封闭的处理器,这使得它可以被内部处理程序访问。你需要根据你的航程范围方法来适应这种情况 - 这是一个很小的海事组织,并且很难看出存在什么路线,但我离题了 - 例如:

      func SomeHandler(db * sql.DB)http.HandlerFunc {
    fn:= func(w http.ResponseWriter,r * http.Request){
    res,err:= db.GetThings()
    //等等
    }

    返回http.HandlerFunc(fn)
    }

    func main(){
    db,err:= sql.Open(...)
    http.HandleFunc(/ some-route,SomeHandler(db))
    / / b



  • 创建一个接受处理程序的自定义处理程序类型 - 例如

      type AppHandler struct {
    Handler func(env * config.Env,w http.ResponseWriter,r * http .Request)
    Env * config.Env

    // ServeHTTP允许你的类型满足http.Handler接口。
    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()
    //等等





    $ b
  • 请注意(无耻插件! )我已经详细介绍了最后一种方法,而且Alex Edwards有关于访问Go程序中数据库池的方法出色的博文


    我可以给出的唯一严格的建议是,您应该回避在请求上下文中传递数据库池的问题,这是效率低下且不好的做法(请求上下文是针对临时的,按请求的对象)。


    At the moment, I try to create a small Web-Project using Go for data handling on the server.

    I try to pass my database-connection to my HandlerFunc(tions) but it does not work as expected. I am pretty new to golang, so maybe I did not understand some basic principles of this lang.

    My main func looks like this:

    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))
    }
    

    My 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
    }
    

    and my routes:

    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,
        },  
    }
    

    So - how can I pass my "env" (or env.DB) to my FuncHandlers? I tried many things, but none of them worked.

    解决方案

    You have three options:

    1. Make your database connection pool a global, so that you don't have to pass it. sql.DB is safe for concurrent access, and this is the easiest approach. The downside is that it makes testing harder and obfuscates "where" the pool is coming from - e.g.

      var db *sql.DB
      
      func main() {
          var err error
          db, err = sql.Open(...)
          // Now accessible globally, no need to pass it around
          // ...
       }
      

    2. Wrap your handlers in a closure, which makes it accessible to the inner handler. You'll need to adapt this to your range-over-routes approach—which is a little obtuse IMO, and makes it harder to see what routes exist, but I digress—for example:

      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. Create a custom handler type that accepts a handler - e.g.

      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.
      }
      

    Note that (shameless plug!) I've written about the last approach in detail, and Alex Edwards has an excellent blog post on approaches to accessing DB pools in Go programs as well.

    The only strict advice I can give is that you should shy away from passing your DB pool around in a request context, which is inefficient and not good practice (request contexts are for temporary, per-request objects).

    这篇关于去使用mux路由器 - 如何将我的数据库传递给我的处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆