Go语言与MongoDB结合开发时,mgo库是早期广泛使用的驱动工具,它提供了简洁的API来完成BSON文档的构建、插入、查询等操作,适合快速实现数据存储需求。BSON作为MongoDB的存储格式,支持更丰富的数据类型,比JSON更适合数据库存储场景。

mgo库环境准备
首先需要安装mgo库,在终端执行以下命令完成安装:
go get gopkg.in/mgo.v2
安装完成后,就可以在项目中引入mgo库进行开发。连接MongoDB的示例代码如下:
package main
import (
"gopkg.in/mgo.v2"
"log"
)
func main() {
// 连接MongoDB,默认连接本地27017端口
session, err := mgo.Dial("127.0.0.1:27017")
if err != nil {
log.Fatal("连接MongoDB失败:", err)
}
defer session.Close()
// 设置一致性模式
session.SetMode(mgo.Monotonic, true)
}
构建BSON文档的两种方式
方式一:使用结构体映射
通过定义结构体,利用bson标签指定字段在MongoDB中的名称,这种方式类型安全,适合固定结构的文档。
package main
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
"time"
)
// 定义用户结构体,bson标签指定存储时的字段名
type User struct {
ID bson.ObjectId `bson:"_id,omitempty"` // omitempty表示插入时自动生成ID
Name string `bson:"name"`
Age int `bson:"age"`
Email string `bson:"email"`
CreateAt time.Time `bson:"create_at"`
}
func main() {
session, err := mgo.Dial("127.0.0.1:27017")
if err != nil {
log.Fatal(err)
}
defer session.Close()
// 选择数据库和集合
c := session.DB("test_db").C("users")
// 构建文档实例
user := User{
Name: "张三",
Age: 25,
Email: "zhangsan@ipipp.com",
CreateAt: time.Now(),
}
// 插入单个文档
err = c.Insert(user)
if err != nil {
log.Fatal("插入文档失败:", err)
}
log.Println("单个文档插入成功")
}
方式二:使用bson.M映射
使用bson.M类型可以动态构建文档,适合结构不固定的场景,不需要提前定义结构体。
package main
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
)
func main() {
session, err := mgo.Dial("127.0.0.1:27017")
if err != nil {
log.Fatal(err)
}
defer session.Close()
c := session.DB("test_db").C("users")
// 动态构建BSON文档
doc := bson.M{
"name": "李四",
"age": 28,
"email": "lisi@ipipp.com",
"hobbies": []string{"读书", "跑步"}, // 支持数组类型
"is_active": true, // 支持布尔类型
}
err = c.Insert(doc)
if err != nil {
log.Fatal("插入动态文档失败:", err)
}
log.Println("动态文档插入成功")
}
批量插入BSON文档提升效率
当需要插入大量文档时,单次插入效率较低,mgo支持批量插入,减少网络请求次数,提升写入性能。
package main
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
"time"
)
type User struct {
ID bson.ObjectId `bson:"_id,omitempty"`
Name string `bson:"name"`
Age int `bson:"age"`
CreateAt time.Time `bson:"create_at"`
}
func main() {
session, err := mgo.Dial("127.0.0.1:27017")
if err != nil {
log.Fatal(err)
}
defer session.Close()
c := session.DB("test_db").C("users")
// 构建批量文档切片
users := []interface{}{
User{Name: "王五", Age: 30, CreateAt: time.Now()},
User{Name: "赵六", Age: 22, CreateAt: time.Now()},
User{Name: "孙七", Age: 35, CreateAt: time.Now()},
}
// 批量插入
err = c.Insert(users...)
if err != nil {
log.Fatal("批量插入失败:", err)
}
log.Println("批量插入成功,共插入", len(users), "条文档")
}
插入操作的注意事项
- 插入文档时如果不指定
_id字段,mgo会自动生成唯一的ObjectId,若手动指定需确保唯一性,否则会插入失败。 - 批量插入时如果其中一条文档出现错误,整个批量操作会失败,需要做好错误捕获和重试逻辑。
- 插入的文档字段名如果包含特殊字符,需要使用
bson.M方式构建,结构体标签无法支持特殊字符字段名。 - 连接MongoDB时建议使用连接池,mgo的session本身支持并发安全,不需要每次操作都创建新连接。
常见问题排查
如果插入操作返回duplicate key error错误,说明插入的文档_id或者设置了唯一索引的字段出现了重复值,需要检查数据唯一性。如果返回连接超时错误,需要检查MongoDB服务是否正常运行,以及连接地址和端口是否正确。