
在 go 中,若想通过函数参数修改外部指针变量的值(如将 `*mgo.session` 从 nil 初始化为有效地址),必须传递**指向该指针的指针(即 `**t`)**,否则仅传递 `*t` 会导致函数内对指针的赋值仅作用于副本,无法影响调用方变量。
这是 Go 值语义特性的典型体现:所有函数参数都是按值传递的。即使你传入的是一个指针 *T,传递的也只是该指针的拷贝——它和原指针指向同一地址,但二者本身是独立的变量。因此,在函数内部对 session 变量重新赋值(如 session = mgo.Dial(...)),只会改变这个局部拷贝的指向,而不会改变 main 中的 session。
要真正修改调用方的指针变量,必须传递其地址,即 &session,此时形参类型需为 **mgo.Session,并在函数内通过解引用 *session 来更新原始指针:
func ConnectToMongo(session **mgo.Session) {
if *session == nil { // 注意:检查的是 *session,而非 session 本身
var err error
*session, err = mgo.Dial("localhost:27028")
if err != nil {
panic(err)
}
}
}
func main() {
var session *mgo.Session // 初始为 nil
ConnectToMongo(&session) // 传入 session 的地址
if session == nil {
fmt.Println("nil. Why?") // 不会执行
} else {
fmt.Println("Connected successfully.") // 正确输出
}
}⚠️ 关键注意事项:
- 第二版代码中你已正确使用 **mgo.Session 和 &session,但原示例存在逻辑错误:if session == nil 应改为 if *session == nil —— 否则条件永远为 false(因为 session 是 **mgo.Session 类型,只要传入了有效地址,它自身就非 nil);
- mgo 已归档不再维护,生产环境建议迁移到官方驱动 mongo-go-driver,其连接管理更符合现代 Go 惯例(如返回 *mongo.Client 并显式错误处理);
- 更推荐的 Go 风格是让函数返回所需对象,而非依赖指针参数“输出”结果,例如:
func NewMongoSession(url string) (*mgo.Session, error) { return mgo.Dial(url) } // 使用: session, err := NewMongoSession("localhost:27028") if err != nil { panic(err) }
这种写法更清晰、更易测试,也避免了指针误用带来的隐蔽问题。










