局部变量
定义:定义在{}里面的变量为局部变量 作用域:只能在{}里面有效;执行到定义的那句话,开始分配内存空间,离开作用域自动进行释放
- 局部变量一定是在函数内部声明
- 在哪个
{}
内部声明; 执行到定义的那句话,开始分配内存,只能在哪个{}
内部访问,离开作用域自动进行释放
看个例子
package main import "fmt" func main() { //定义在{}里面的变量就是局部变量,只能在{}里面有效 //执行到定义变量那句话,才开始分配空间,离开作用域自动释放 //作用域,变量其作用的范围 if flag := 3; flag == 3 { fmt.Println("flag = ", flag) } //flag = 4 不能在if外面执行 报错:undefined: flag 未定义的标记 }
全局变量
定义:在函数外部的变量称为全局变量 作用域:同一个包内的任何地方
- 小写,整个包可以访问
- 大写,跨包可以访问
package constant var A = 12123 var B = map[string]string{} var c = "xiaoming" func Init() { A = 1321312 B["default"] = "default" }
测试:同一个包可以访问
package constant import ( "fmt" "testing" ) func TestGlobal(t *testing.T) { //全局变量声明到函数外部,整个包都可以访问 //如果全局变量首字母大写,跨包也可以访问. fmt.Println(c) }
执行结果:
=== RUN TestGlobal xiaoming --- PASS: TestGlobal (0.00s) PASS
测试:跨包访问
package variable import ( "fmt" //"go/constant" "testing" "/GoProject/main/gobase/constant" ) func TestGlobal(t *testing.T) { constant.Init() fmt.Println(constant.A) fmt.Println(constant.B["default"]) fmt.Println(constant.c) // 会报错 }
注释掉报错那一行,执行结果如下:
=== RUN TestGlobal 1321312 default --- PASS: TestGlobal (0.00s) PASS
全局变量要避免的坑:例如定义了一个全局变量, 然后又使用了 :=
给全局变量赋值, 此时会出现问题。看下面的例子:
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]
远远是因为 使用的是 :=
对全局变量赋值,结果是全局变量未赋值是个 nil, init 中的 dConn
使用 :=
生成的,这里的 dbConn
是局部变量, 全局变量 dbConn
并没有赋值,还是 nil
。
还有个坑,最近看代码, 发现 全局变量名字一样,然后,在 init
也初始化了, 然后跨包应用这个全局变量时,这个全局变量还是个 nil,
查了半天,才看到全局变量的名字是一样的,但是归属不同的 包 A, B , 包 A 初始化了,但是用的是 包 B 的全局变量的值, 包B 全局变量并没有被初始化!!!!