go中易错的全局变量空指针

348 阅读1分钟

前言

go中的语法算是比较方便的,但是今天突然遇到一个全局变量初始化后仍然是空指针的问题,review了好几遍也没有发现问题,后来看了一下别人的代码才发现原来这个地方有问题

错误示例

很多时候我们都需要一些全局变量用在项目中的各个地方
比如这里有段简单的初始化一个gorm.DB指针的函数,Init()函数初始化了gorm.DB指针之后,我们就可以使用它在项目的任意地方进行mysql数据库的操作

var (
	Db *gorm.DB
)

func Init() {
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", username, password, host, port, dbname)

	Db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

	if err != nil {
        panic(err)
	}
}

乍一看这段代码好像没什么问题,但是当你在别的地方使用Db指针进行mysql操作时,会出现空指针的报错


这是因为第8行代码有问题,此时初始化的Db并不是全局变量,而是Init()函数里面的局部变量

我们都知道,局部变量的声明往往会覆盖全局变量,当你用:=符号时,你可能只是想声明一个err,但是很不幸的是,Db也默认为局部变量声明了

正确示例

我们只需要小改一个地方即可摆脱这个问题

var (
	Db *gorm.DB
)

func Init() {
  var err error // 只需要提前声明局部变量err
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", username, password, host, port, dbname)

	Db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) // 然后这里改成=即可

	if err != nil {
        panic(err)
	}
}

这样Db使用的就是全局变量了