【问题标题】:How do I call mongoDB CRUD method from handler?如何从处理程序调用 mongoDB CRUD 方法?
【发布时间】:2014-01-13 22:22:01
【问题描述】:

我用一些 CRUD 方法编写了一个简单的 MongoDB 包:

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
}

我有一个 server.go,我在其中创建了一个 Http 服务器并为不同的 URL 提供了处理程序。我希望能够连接到 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(title, description string) 方法。我应该创建一个全局数据库连接变量吗?

【问题讨论】:

    标签: mongodb go


    【解决方案1】:

    是的,全局会话是处理该问题的简单方法。然后,在每个处理程序的顶部,您可以执行以下操作:

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

    以便每个处理程序都有自己的会话来使用。

    请注意,复制和关闭会话是廉价操作,它在内部将针对连接池工作,而不是为每个创建的会话建立新连接。

    【讨论】:

    • 首先感谢您回答这些问题。作为mgo的主要开发者,特别权威。我正在查看 mgo/session.go 中的代码,例如 Apply() 已经克隆了会话,那么为什么需要我们自己创建全局会话的副本?
    【解决方案2】:

    两个简单的方法:

    1.全局数据库会话

    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.每个请求都有一个新的数据库连接

    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()
    
    } 
    
    ......
    

    更好的解决方案:

    您可以创建一个数据库会话池,然后在处理 请求您选择一个并放入该请求的上下文中。然后 请求完成后,您将连接推回池中。

    如果池为空,则创建一个新连接 如果池已满 你关闭连接

    更多信息,请点击here

    【讨论】:

    • 全局变量的第一个解决方案,我之前试过了,还是不行。我不断收到此错误:http:panic serving [::1]:55642: runtime error: invalid memory address or nil pointer dereference
    • 定义一个全局变量:var mongoConn *benkend.MongoDBConn,在main函数中连接mongodb:mongoConn = backend.NewMongoDBConn()。我改了上面的代码,就可以了。
    • 创建数据库会话池没有意义。当会话关闭时,mgo 将在内部缓存资源,并在创建新会话时重用这些资源。
    猜你喜欢
    • 2023-04-07
    • 2014-11-12
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多