2012-12-24 89 views
1

我寫了一個簡單的MongoDB封裝的一些CRUD方法:如何從處理程序調用mongoDB CRUD方法?

package backend 

import "labix.org/v2/mgo" 

type MongoDBConn struct { 
    session *mgo.Session 
} 

type ToDo struct { 
    Title  string 
    Description string 
} 

func NewMongoDBConn() *MongoDBConn { 
    return &MongoDBConn{} 
} 

func (m *MongoDBConn) Connect(url string) *mgo.Session { 
    session, err := mgo.Dial(url) 
    if err != nil { 
     panic(err) 
    } 
    m.session = session 
    return m.session 
} 

func (m *MongoDBConn) Stop() { 
    m.session.Close() 
} 

func (m *MongoDBConn) AddToDo(title, description string) (err error) { 
    c := m.session.DB("test").C("people") 
    err = c.Insert(&ToDo{title, description}) 
    if err != nil { 
     panic(err) 
    } 
    return nil 
} 

我有,我創建一個HTTP服務器,並有不同的URL處理器創建一個server.go。我希望能夠連接到MongoDB並在特定處理程序中調用AddToDo方法。我可以從我的服務器的主要方法連接到數據庫:

import (
    "./backend" 
     //other boilerplate imports 
) 

func AddHandler(writer http.ResponseWriter, request *http.Request) { 
    log.Printf("serving %v %v", request.Method, request.URL.Path[1:]) 
    if request.Method != "POST" { 
     serve404(writer) 
     return 
    } 
    title := request.FormValue("title") 
    description := request.FormValue("description") 
    fmt.Fprintf(writer, " title description %v %v", title, description) 
//I can't call mongoConn.AddToDo(title, description) from here 

}  
func main() { 
     //connect to mongoDB 
     mongoConn := backend.NewMongoDBConn() 
     _ = mongoConn.Connect("localhost") 
     defer mongoConn.Stop() 
    } 

但我不知道如何調用mongoConn.AddToDo(標題,描述字符串)方法從處理程序。我應該創建一個全局數據庫連接變量?

回答

2

兩個簡單的方法:

1.global數據庫會話

package main 


import (
    "net/http" 
    "log" 
    "fmt" 
    "./backend" 
) 


var mongoConn * backend.MongoDBConn 

func AddHandler(w http.ResponseWriter, r *http.Request) { 
    log.Printf("serving %v %v", r.Method, r.URL.Path[1:]) 
    if r.Method != "POST" { 
     fmt.Fprintln(w, "Not POST Method ") 
     return 
    } 
    title := r.FormValue("title") 
    description := r.FormValue("description") 



    fmt.Fprintf(w, " title description %v %v", title, description) 
//I can't call mongoConn.AddToDo(title, description) from here 
    mongoConn.AddToDo(title, description) 
}  

const AddForm = ` 
<html><body> 
<form method="POST" action="/add"> 
Name: <input type="text" name="title"> 
Age: <input type="text" name="description"> 
<input type="submit" value="Add"> 
</form> 
</body></html> 
` 
func Index(w http.ResponseWriter, r *http.Request) { 
    fmt.Fprintln(w, AddForm) 
} 

func main() { 
     //connect to mongoDB 


     mongoConn = backend.NewMongoDBConn() 
     _ = mongoConn.Connect("localhost") 
     defer mongoConn.Stop() 

     http.HandleFunc("/", Index) 
     http.HandleFunc("/add", AddHandler) 

     log.Println("Start Server:") 
     err := http.ListenAndServe(":8080", nil) 

     if err != nil { 
      log.Fatal("ListenAndServe:", err) 
     } 
} 

2.A在每次請求新的數據庫連接

import (
    "./backend" 
     //other boilerplate imports 
) 

func AddHandler(writer http.ResponseWriter, request *http.Request) { 
    log.Printf("serving %v %v", request.Method, request.URL.Path[1:]) 
    if request.Method != "POST" { 
     serve404(writer) 
     return 
    } 
    title := request.FormValue("title") 
    description := request.FormValue("description") 
    fmt.Fprintf(writer, " title description %v %v", title, description) 
    //................ 
    mongoConn := backend.NewMongoDBConn() 
    _ = mongoConn.Connect("localhost") 
    mongoConn.AddToDo(title, description) 
    //.................... 
    mongoConn.Stop() 

} 

...... 

一個更好的解決方案:

You could create a pool of db sessions, then before processing the request you pick one and put in the context of that request. Then after the request is done you push the connection back to the pool.

If the pool is empty you create a new connection If the pool is full you close the connection

欲瞭解更多信息,請點擊here

+0

全局變量的第一個解決方案,我早先嚐試過,它不起作用。我一直得到這個錯誤: http:panic serving [:: 1]:55642:runtime error:invalid memory address or nil pointer dereference – jwesonga

+0

define a global variable:'var mongoConn * benkend.MongoDBConn',connect mongodb in main function: 'mongoConn = backend.NewMongoDBConn()'。我改變了上面的代碼,它的工作原理。 – pexeer

+1

創建數據庫會話池沒有意義。當會話關閉時,mgo會內部緩存資源,並且每當創建一個新會話時都會重用這些資源。 –

3

是的,全局會話是處理這個問題的簡單方法。然後,在每一個處理器的頂部,你可以做線沿線的:

func handler(...) { 
    session := globalSession.Copy() 
    defer session.Close() 
} 

使每個處理器都有自己的會議的工作。

請注意,複製和關閉會話是便宜的操作,它在內部將針對連接池工作,而不是爲創建的每個會話建立新連接。

+0

首先感謝您回答這些問題。作爲mgo的主要開發者,它是特別權威的。 我正在查看mgo/session.go中的代碼,例如Apply()已經克隆了會話,爲什麼需要自己創建globalsession的副本? – Alkaline

相關問題