概念定义:
全局变量:
- 定义:在函数外部的变量称为全局变量
- 作用域:同一个包内的任何地方
局部变量:
- 定义:定义在{}里面的变量为局部变量
- 作用域:只能在{}里面有效;执行到定义的那句话,开始分配内存空间,离开作用域自动进行释放
问题描述:
在我们学习go语言时,通常会使用golang的一个语法糖:=
来给变量赋值,这种方式可以节省掉我们定义变量的代码,让代码变的更加简洁。
但是如果你定义了一个全局变量,又不小心用:=
来给它赋值,就会出现一些问题。如下:
package dbops
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"log"
)
var (
dbConn *sql.DB
err error
)
func init() {
dbConn, err := sql.Open("mysql","root:000000@tcp(localhost:3306)/server?charset=utf8")
if err != nil{
panic(err.Error())
}
log.Println(dbConn)
}
func main() {
log.Println("查看全局变量dbConn:",dbConn)
}
在这里我们用的是 := 给全局变量赋的值,结果是全局变量并未赋值成功。执行会报错。
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x5b0a61]
原因分析:
执行之后,发现在init中明明给dbConn赋值,单在main中却是nil。弄清楚局部变量和全局变量,不难发现,init中的dbConn是用:=
生成的,所以这里的dbConn是局部变量,只不过是在init函数中覆盖了全局变量dbConn。全局变量dbConn并没有被赋值,它还是原来的nil。
解决方法:
将 := 用 = 替换
dbConn, err = sql.Open("mysql","root:000000@tcp(localhost:3306)/server?charset=utf8")
达到预期目的。
归纳总结:
- 尽量少的使用全局变量。
- 尽量少的使用
:=
语法糖。 - 使用
:=
的时候要确保左值没有被定义过。
要对全局变量,局部变量有明确清晰的认知,使用起来就能够游刃有余,得心应手。