為什麼 Go 有兩種宣告變數的方式,有什麼區別,哪種好?

煎魚 發表於 2022-01-17
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 有兩種宣告變數的方式,有什麼區別,哪種好?

問題是:使用哪一種宣告方式,令人困惑。

題主糾結的原因在於:

  • 如果一個只是另一個的速記方式,為什麼它們的行為會不同?
  • 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 的兩種變數宣告放水。並且針對短宣告存在的場景進行了說明。

主要是:

  • 程式碼塊的分組宣告。
  • 變數的初始值指定。
  • 區域性變數,區分作用域。
  • 重新宣告變數。

你覺得變數宣告上,還有沒有別的優缺點呢,歡迎在評論區交流:)

若有任何疑問歡迎評論區反饋和交流,最好的關係是互相成就,各位的點贊就是煎魚創作的最大動力,感謝支援。

文章持續更新,可以微信搜【腦子進煎魚了】閱讀,本文 GitHub github.com/eddycjy/blog 已收錄,學習 Go 語言可以看 Go 學習地圖和路線,歡迎 Star 催更。

參考