golang mgo 使用

golang使用mongodb,目前比较多人用的是mgo(pronounced as mango)

github地址
官网
文档


直接上官方example的代码

Example

首先是要获得模块


go get gopkg.in/mgo.v2

下一步(这里假设你已经会搭建go的环境和了解go的库配置)

package main

import (
        "fmt"
    "log"
        "gopkg.in/mgo.v2"
        "gopkg.in/mgo.v2/bson"
)

type Person struct {
        Name string
        Phone string
}

func main() {
        session, err := mgo.Dial("server1.example.com,server2.example.com")//传入数据库的地址,可以传入多个,具体请看接口文档 

        if err != nil {
                panic(err)
        }
        defer session.Close() //用完记得关闭

        // Optional. Switch the session to a monotonic behavior.
        session.SetMode(mgo.Monotonic, true) //读模式,与副本集有关,详情参考https://docs.mongodb.com/manual/reference/read-preference/ & https://docs.mongodb.com/manual/replication/

        c := session.DB("test").C("people")
        err = c.Insert(&Person{"Ale", "+55 53 8116 9639"},
                   &Person{"Cla", "+55 53 8402 8510"})
        if err != nil {
                log.Fatal(err)
        }

        result := Person{}
        err = c.Find(bson.M{"name": "Ale"}).One(&result) //如果查询失败,返回“not found”
        if err != nil {
                log.Fatal(err)
        }

        fmt.Println("Phone:", result.Phone)
}

Dial函数,参考https://godoc.org/gopkg.in/mgo.v2#Dial
传入参数的格式:

  • [mongodb://][user:pass@]host1[:port1][,host2[:port2],…][/database][?options]

例如

  • “mongodb://admin:123456@localhost:27017/admin” //如果mongodb打开了auth功能,必须传入账号密码才可以访问

实际应用

例子是在main函数直接dial,不过很多时候我们想在其它模块里面使用,尤其是在goruntime(有时候被称作协程)使用,这就需要稍微改造一下。

高并发环境里面,不可能每次使用前dial,因为重新建立tcp连接是一件十分耗时的操作。

一般来说,会使用连接池。一般连接池的设计,有两个很重要的参数,Max Active数量和Max Idle数量,max active意思是最多可以建立多少连接,max idle就是在空闲的时候保持的连接数量,方便随时调用,可以避免重新与数据库建立连接。

mgo内部已经做了连接池的机制,默认的连接池大小是4096,注意应该在初始化的时候设置好连接池的数量

以下给出一个demo

mongodb.go 详细内容

package mongodb

import (
    "gopkg.in/mgo.v2"
    "time"
)



//global
var GlobalMgoSession *mgo.Session


func init() {
    globalMgoSession, err := mgo.DialWithTimeout("mongodb://admin:123456@localhost:27017/admin", 10 * time.Second)
    if err != nil {
        panic(err)
    }
    GlobalMgoSession=globalMgoSession
    GlobalMgoSession.SetMode(mgo.Monotonic, true)
    //default is 4096
    GlobalMgoSession.SetPoolLimit(300)
}

func CloneSession() *mgo.Session {
    return GlobalMgoSession.Clone()
}

接着test
mongodb_test.go

package mongodb_test

import (
    "fmt"
    "×××/db/mongodb" //这里要改成mongodb.go的文件存放路径
    "gopkg.in/mgo.v2/bson"
    "time"
    "testing"
)

type User struct {
    Id_       bson.ObjectId `bson:"_id"`
    Name      string `bson:"name"`
    Age       int `bson:"age"`
    JoinedAt  time.Time `bson:"joned_at"`
    Interests []string `bson:"interests"`
}

func TestMongodb(t *testing.T) {
    session := mongodb.CloneSession()//调用这个获得session
    defer session.Close()  //一定要记得释放

    c := session.DB("test1").C("people")
    err := c.Insert(&User{Id_: bson.NewObjectId(),
        Name: "Jimmy Kuu",
        Age: 33,
        JoinedAt: time.Now(),
        Interests: []string{"Develop", "Movie"} })

    if err != nil {
        panic(err)
    }

    var users []User
    err=c.Find(nil).Limit(5).All(&users)
    if err != nil {
        panic(err)
    }
    fmt.Println(users)

}

连接池我设成了500,这里可以根据个人需求自己选择,也可以使用默认设置。
强调一下,一定要记得调用 defer session.Close() ,连接池里面会复用释放掉的连接的。
其实这里的单元测试不是很正规,不方便做成功的判断。。可以test -v,直接看控制台的输出。

关于mgo连接池的复用
下面给出Clone方法的注释

// Clone works just like Copy, but also reuses the same socket as the original
// session, in case it had already reserved one due to its consistency
// guarantees.  This behavior ensures that writes performed in the old session
// are necessarily observed when using the new session, as long as it was a
// strong or monotonic session.  That said, it also means that long operations
// may cause other goroutines using the original session to wait.
func (s *Session) Clone() *Session {
    s.m.Lock()
    scopy := copySession(s, true)
    s.m.Unlock()
    return scopy
}

相关参考文档
https://my.oschina.net/ffs/blog/300148
http://www.cnblogs.com/shenguanpu/p/5318727.html

你可能感兴趣的:(golang,db)