golang使用mongodb,目前比较多人用的是mgo(pronounced as mango)
github地址
官网
文档
直接上官方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
传入参数的格式:
例如
例子是在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