2012-12-24 88 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

相关问题