為什么 Go 有兩種聲明變量的方式,有什么區別,哪種好?
本文轉載自微信公眾號「腦子進煎魚了」,作者陳煎魚 。轉載本文請聯系腦子進煎魚了公眾號。
大家好,我是煎魚。
有一位讀者剛入門 Go ,提了一個很有意思的問題:Go 有幾種聲明變量的方式,作為初學者,到底用哪種,有什么區別,又為什么要有多種聲明方式呢?
為此,煎魚將和大家一起探索這個問題。
變量聲明
在 Go 中,一共有 2 種變量聲明的方式,各有不同的使用場景。
分別是:
- 標準變量聲明(Variable declarations)。
- 簡短變量聲明(Short variable declarations)
標準聲明
變量聲明創建了一個或多個變量,為它們綁定了相應的標識符,并給每個變量一個類型和初始值。
使用語法:
- VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
- VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
案例代碼:
- var i int
- var U, V, W float64
- var k = 0
- var x, y float32 = -1, -2
- var (
- i int
- u, v, s = 1.0, 2.0, "腦子進煎魚了"
- )
簡短聲明
一個短變量聲明。使用語法:
- ShortVarDecl = IdentifierList ":=" ExpressionList .
案例代碼:
- s := "煎魚進腦子了"
- i, j := 0, 10
- f := func() int { return 7 }
- ch := make(chan int)
- r, w, _ := os.Pipe()
- _, y, _ := coord(p)
網友疑惑
在我們群里的 Go 讀者提了這問題后,我也搜了搜相關資料。發現在 stackoverflow 上也有人提出了類似的疑惑:
問題是:使用哪一種聲明方式,令人困惑。
題主糾結的原因在于:
- 如果一個只是另一個的速記方式,為什么它們的行為會不同?
- Go 的作者出于什么考慮,讓兩種方式來聲明一個變量(為什么不把它們合并成一種方式)?只是為了迷惑我們?
- 有沒有其他方面需要我在使用時留心的,以防掉進坑里?
下面我們結合 stackoverflow 的這個提問內容和回答,進一步展開,帶大家看看里面到底賣的是什么 “藥”。
先思考一下:標準聲明和短聲明,這兩者的區別的在哪那里,又或是憑喜好隨意使用?
區別在哪
代碼塊的分組聲明
使用包含關鍵字 var 的聲明語法時,和其他 package、import、const、type、var 等關鍵字一樣,是可以進行分組的代碼塊聲明的。
例如:
- var (
- i int
- u, v, s = 1.0, 2.0, "腦子進煎魚了"
- )
而短聲明,是不支持的。
變量的初始值指定
使用標準的變量定義時,我們可以只聲明,不主動地定義該變量的初始值(缺省會給零值)。
例如:
- var (
- i int
- s string
- )
而短聲明則不行,必須要在程序中主動地去對變量定義一個值。
例如:
s := "腦子進煎魚了"
此處即使是定義的空字符串,那也屬于是用戶側主動定義的,而非缺省的零值。
局部變量,區分作用域
在編寫程序時,我們經常會有一些局部變量聲明,且作用域是有限的。
可以看看自己的代碼,這種時候,我們都會采取短聲明的方式。
例如:
- for idx, value := range array {
- // Do something with index and value
- }
- if num := runtime.NumCPU(); num > 1 {
- fmt.Println("Multicore CPU, cores:", num)
- }
短聲明在這類場景下有明確的優勢,標準的變量聲明在這類場景不討好。
重新聲明變量
在 Go 語言規范中有明確提到,短變量聲明是可以重新聲明變量的,這是一個高頻重新聲明的覆蓋動作。
如下:
- var name = "煎魚.txt"
- fi, err := os.Stat(name)
- if err != nil {
- log.Fatal(err)
- }
- data, err := ioutil.ReadFile(name)
- if err != nil {
- log.Fatal(err)
- }
- ...
上述代碼中,err 變量就是不斷地被反復定義。在 if err != nil 猖狂的現在,短變量在此處的優勢,簡直是大殺器了。
總結
相信很多小伙伴初入門時都為此糾結過一下,又或是很多教程壓根就沒有說清楚兩者變量聲明的區別。
在今天這篇文章中,我們介紹了 Go 的兩種變量聲明放水。并且針對短聲明存在的場景進行了說明。
主要是:
- 代碼塊的分組聲明。
- 變量的初始值指定。
- 局部變量,區分作用域。
- 重新聲明變量。
你覺得變量聲明上,還有沒有別的優缺點呢,歡迎在評論區交流:)
參考
GoLang Variable Declaration
Why there are two ways of declaring variables in Go, what's the difference and which to use?
What is the best practice when declaring variables in go (golang)? E.G. should I use "var x int = 1" or just "x := 1"?