dqc42632 2015-11-11 08:46
浏览 96
已采纳

使用Mux Router-如何将数据库传递给处理程序

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.

  • 写回答

2条回答 默认 最新

  • dongpu1908 2015-11-11 09:20
    关注

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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 shape_predictor_68_face_landmarks.dat
  • ¥15 slam rangenet++配置
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题