2014-12-03 49 views
1

我正在嘗試在我的Go應用中配置mongo。我正在使用Gin框架。我也用mongo的mgo V2驅動程序。我想連接到mongo作爲一箇中間件。下面是我的了:配置mongo與杜松子酒golang框架

func Run(cfg common.Config) error { 

doWorkResource := &DoWorkResource{db: dbmap} 

r := gin.New() 

r.Use(middleware.DB()) 


r.POST("/register", doWorkResource.Register) 
r.POST("/login", doWorkResource.Login) 

r.Run(cfg.SvcHost) 

return nil 
} 

這是DB函數:

func DB() gin.HandlerFunc { 
    session, err := mgo.Dial("localhost:27017") 
    if err != nil { 
     panic(err) 
    } 

    defer session.Close() 

    return func(c *gin.Context) { 
     s := session.Clone() 

     db := s.DB("testing").C("testData") 
     err = db.Insert(&Person{"Ale", "+55 53 8116 9639"}, 
      &Person{"Cla", "+55 53 8402 8510"}) 
     if err != nil { 
      log.Fatal(err) 
     } 

     c.Next() 
    } 
} 

type Person struct { 
    Name string 
    Phone string 
} 

,如果我直接從主功能運行時,執行插入,但如果它是從DB run()函數。實際上,我在DB()函數的return語句內進行了記錄,並且沒有執行任何內容。我有一種感覺,我需要調用它作爲參數傳遞給我的終點之一,但是當我做,我得到

cannot use middleware.DB (type func() gin.HandlerFunc) as type gin.HandlerFunc in argument to r.RouterGroup.POST

回答

1

看起來像你的問題就在這裏:

defer session.Close() 

什麼當你註冊中間件時,你確實在做的不是每次調用中間件都調用中間件,而是定義每次調用時要做的事情。首先運行一組初始命令。這將是這部分:

session, err := mgo.Dial("localhost:27017") 
    if err != nil { 
    panic(err) 
} 

defer session.Close() 

然後返回一組指令運行每次你的端點中的一個被擊中的時候,這將是這一部分:

s := session.Clone() 

db := s.DB("testing").C("testData") 
err = db.Insert(&Person{"Ale", "+55 53 8116 9639"}, 
    &Person{"Cla", "+55 53 8402 8510"}) 
if err != nil { 
    log.Fatal(err) 
} 

c.Next() 

當你從返回中間件初始化程序,它激活defer聲明。然後,當第一個電話進入並嘗試運行您以HandlerFunc的形式返回的指令時,它將失敗,因爲它正在嘗試使用的會話已關閉。

+0

啊有道理。謝謝@Verran。我最終創建了一個獨立的函數來初始化數據庫,並分別爲每個端點進行交互。我不希望每當端點被擊中時都要執行相同的數據庫操作。除了日誌記錄之外,是否有中間件用於其他用途(您希望爲每個端點執行相同的操作)? – dmonay 2014-12-04 01:44:25

+0

關於我的頭頂,我會說認證,比如檢查OAuth密鑰,檢查白名單上的IP等。如果您想創建初始數據庫會話並通過中間件返回原始會話的副本對於每個單獨的連接來保持數據庫調用併發,只要您不關閉調用Copy()的初始會話,就可以這樣做。我相信除了基於個人用例之外,還有更多的場景,但那只是我的頭頂。 – Verran 2014-12-04 17:21:00

相關問題