处理需要访问Go中的数据库的中间件

时间:2016-11-01 23:29:48

标签: go

我遇到了创建中间件的问题,该中间件将链接到其他路由并需要访问数据库,并且不确定如何解决此问题。

我将所有应用程序上下文存储在一个名为 func SomeHandler(appC *AppContext, next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { // Access the database using appC.db // Logic that requires access to the database. next.ServeHTTP(w, r) } return http.HandlerFunc(fn) } } 的结构中,包括数据库。我想创建一个看起来像这样的函数处理程序:

main.go

someHandler := middleware.SomeHandler(&appC) 中,我尝试过:

not enough arguments in call to middleware.SomeHandler

但是,我收到错误<form action="example.php" method="POST"> <select name="test" id="test"> <?php $dir="./files"; if (is_dir ($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) != false) { if ($file != ".." && $file != "." && strtolower(substr($file,strrpos($file,'.') +1)) == 'txt) { echo "option value =\"$file\"> $file </option>"; } } } } ?> </select> <input type="Submit" value="Ok"> </form> 。解决这个问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

您收到的错误是由于未提供第二个参数next http.Handler

在如何使用中间件的情况下,我建议您查看http.ServeMux https://golang.org/src/net/http/server.go?s=57308:57433#L1890的实现,它基本上会执行您尝试做的事情(然后是一些)虽然路由。因此,使用http.Handler结构可能比使用Handler函数更容易,这样您在函数中作为next http.Handler参数的Handler只是结构中的一个字段。父处理程序可以在其ServeHTTP()内进行调用。

总而言之,您可能希望使用实现http.Handler接口的结构。这样它就可以拥有子处理程序和数据库访问权限。这样你也不必继续传递这个AppContext

答案 1 :(得分:-1)

我不会过早设置上下文。特别是请求作用域。

我宁愿创建一个小而专用的中间件,用于将数据库会话从池传递到上下文中,并检索在主处理程序中为请求创建的所述会话。

func DBSession(sess *mgo.Session, next http.Handler) http.Handler {
    return http.HandlerFunc(
        func(w http.ResponseWriter, r *http.Request) {
            // Create a new session for the scope of the request
            s := sess.Copy()
            // Make it close when exiting scope
            defer s.Close()

            // Add the new session (actually a pointer to it)
            // acessible via the name "_sess"
            ctx = context.WithValue(r.Context(), "_sess", s)

            // execute the next handler
            next(w, r.WithContext(ctx))
        })
}

现在您可以在main.go中使用此中间件

package main

import (
    "net/http"

    "gopkg.in/mgo.v2"
)

func sayHello(w http.ResponseWriter, r *http.Request) http.Handler{

  return http.HandlerFunc(
    func (w http.ResponseWriter, r *http.Request) {
      s := r.Context().Value("_sess").(*mgo.Session)
      // Do something with your database here.
    }
  )

}

func main() {

    // Ignoring err for brevity
    sess, _ := mgo.Dial("localhost:27017")

    // Magic happens here: the sayHello Handler is wrapped in the
    // DBSession middleware, which makes the session available
    // as context param _sess and closes the session after sayHello
    // executed. No clutter in your controller for setting up and tearing down
    // the session, no way you can forget to close it.
    http.Handle("/", middleware.DBSession(sess, sayHello))
}