2016-11-01 51 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)) 
} 
相關問題