使用Golang globalsign/mgo调用MongoDB $in操作符遇切片地址错误
解决mgo库中"result argument must be a slice address" panic问题
这个panic的核心原因很明确:你在调用mgo的All()方法时,传入的结果参数不是切片的指针。mgo的查询方法(比如All())需要通过指针来修改外部的切片,直接传切片值的话,方法内部无法对原切片进行赋值操作,就会触发这个错误。
下面是完整的正确实现,对应你需要的MongoDB查询语句:
1. 定义对应MongoDB集合的结构体
首先要定义和cluster集合匹配的Go结构体,注意bson标签要和MongoDB字段名完全对应:
type Cluster struct { ClusterName string `bson:"clusterName"` // 这里可以添加你的集合中其他字段,比如ID、创建时间等 }
2. 正确的ReadClusters函数实现
import ( "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) func ReadClusters(session *mgo.Session, targetClusterNames []string) ([]Cluster, error) { // 复制会话,避免并发场景下的会话冲突问题 sessionCopy := session.Copy() defer sessionCopy.Close() // 切换到目标数据库和集合(替换成你的实际数据库名) coll := sessionCopy.DB("your_database_name").C("cluster") // 定义接收结果的切片 var clusters []Cluster // 关键:传入切片的地址&clusters,而不是切片本身 query := bson.M{"clusterName": bson.M{"$in": targetClusterNames}} err := coll.Find(query).All(&clusters) if err != nil { return nil, err } return clusters, nil }
你可能犯的错误点
如果之前的代码触发了panic,很大概率是你在调用All()的时候直接传了切片值,而不是指针:
错误写法示例:
var clusters []Cluster // 这里传的是clusters(切片值),不是&clusters(切片指针) err := coll.Find(query).All(clusters)
额外注意事项
- 每次处理请求时一定要复制会话(
session.Copy()),mgo的会话不是并发安全的,直接复用会导致奇怪的问题 - 如果后续需要查询单个文档,使用
One()方法时同样要传指针(比如var cluster Cluster; err := coll.Find(query).One(&cluster)) - 确保你的结构体字段的bson标签和MongoDB中的字段名完全一致,否则会出现字段值为空的情况
内容的提问来源于stack exchange,提问作者sheldonzy




