在 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.") // 正确输出 } }
⚠️ 关键注意事项:
func NewMongoSession(url string) (*mgo.Session, error) {
return mgo.Dial(url)
}
// 使用:
session, err := NewMongoSession("localhost:27028")
if err != nil { panic(err) }这种写法更清晰、更易测试,也避免了指针误用带来的隐蔽问题。