概念定義:
全局變量:
- 定義:在函數外部的變量稱爲全局變量
- 作用域:同一個包內的任何地方
局部變量:
- 定義:定義在{}裏面的變量爲局部變量
- 作用域:只能在{}裏面有效;執行到定義的那句話,開始分配內存空間,離開作用域自動進行釋放
問題描述:
在我們學習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")
達到預期目的。
歸納總結:
- 儘量少的使用全局變量。
- 儘量少的使用
:=
語法糖。 - 使用
:=
的時候要確保左值沒有被定義過。
要對全局變量,局部變量有明確清晰的認知,使用起來就能夠遊刃有餘,得心應手。