Go语言跨包导入Xorm实例为何呈现nil状态?
问题根源:Go语言的变量遮蔽(Variable Shadowing)
嘿,这坑我之前也踩过!你在db/xorm.go的init函数里犯了一个Go语言里超典型的错误——变量遮蔽,导致包级的Xorm变量根本没被正确赋值。
为什么会出现这种情况?
你看这段关键代码:
Xorm, err := xorm.NewEngine("postgres", url)
这里的:=是Go的短变量声明运算符,它会在当前函数作用域内创建两个新的局部变量:Xorm和err。也就是说,你在这里操作的Xorm根本不是包级别定义的var Xorm *xorm.Engine,而是一个函数内的临时变量!
所以你在init里打印的是这个局部的Xorm(它确实被赋值了,所以非nil),但包级的Xorm从始至终都是初始的nil,main函数自然拿不到正确的值。
至于你说的普通字符串变量没问题,是因为你给它赋值的时候用的是=而不是:=,直接修改了包级变量,没有创建局部变量遮蔽它。
怎么修复?
只需要避免短变量声明创建局部的Xorm,直接给包级变量赋值就行,有两种常见写法:
写法一:先单独声明err变量(推荐)
package db import ( _ "github.com/lib/pq" "xorm.io/xorm" ) var Xorm *xorm.Engine func init() { url := "user=test host=localhost password=test port=15432 dbname=test sslmode=disable" var err error // 先在函数内声明err变量 Xorm, err = xorm.NewEngine("postgres", url) // 用=赋值,操作的是包级Xorm println(Xorm) // 现在打印的是包级变量 if err != nil { panic(err) } }
写法二:先创建局部引擎变量,再赋值给包级变量
func init() { url := "user=test host=localhost password=test port=15432 dbname=test sslmode=disable" engine, err := xorm.NewEngine("postgres", url) if err != nil { panic(err) } Xorm = engine // 把局部变量的值赋给包级变量 println(Xorm) }
第一种写法更清晰,也符合Go的编码习惯,优先推荐。
验证效果
修改后再运行main.go,println(db.Xorm)就会打印出引擎的内存地址,而不是nil了。
内容的提问来源于stack exchange,提问作者shshsh12
相关产品推荐
相关产品推荐

