2016-11-01 54 views
0

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

我将所有的应用程序上下文都存储在一个名为AppContext的结构中。我想创建一个函数处理程序,它看起来是这样的:

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。解决这个问题最好的办法是什么?

+2

顺便说一句,你可以使用这个中间件上下文在围棋,https://golang.org/pkg/context/的事情,让appContext名字可能会让人困惑。 –

+2

坦率地说:阅读文档和[参观](https://tour.golang.org/welcome/1)。在采取任何进一步措施之前,您至少应该能够阅读方法签名。此外,我不会为所有请求设置相同的“超级”上下文。 –

回答

0

你得到的错误是由于没有提供第二个参数next http.Handler

在如何介绍中间件的情况下,我推荐看一看http.ServeMuxhttps://golang.org/src/net/http/server.go?s=57308:57433#L1890的实现,它基本上是做你正在尝试做的(然后是一些)路由。因此,使用http.Handler结构可能比使用Handler函数更容易,这样您的函数中作为next http.Handler参数的Handler(s)就是父处理函数可以调用的结构中的一个字段在其ServeHTTP()内。

因此,为了总结我的观点,您可能希望使用实现http.Handler接口的结构。这样它可以有子处理程序和数据库访问。这样你就不必一直传递这个AppContext

-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)) 
} 
相关问题