為什么 Go 有兩種聲明變量的方式,有什么區(qū)別,哪種好?
本文轉(zhuǎn)載自微信公眾號(hào)「腦子進(jìn)煎魚了」,作者陳煎魚 。轉(zhuǎn)載本文請(qǐng)聯(lián)系腦子進(jìn)煎魚了公眾號(hào)。
大家好,我是煎魚。
有一位讀者剛?cè)腴T Go ,提了一個(gè)很有意思的問題:Go 有幾種聲明變量的方式,作為初學(xué)者,到底用哪種,有什么區(qū)別,又為什么要有多種聲明方式呢?
為此,煎魚將和大家一起探索這個(gè)問題。
變量聲明
在 Go 中,一共有 2 種變量聲明的方式,各有不同的使用場(chǎng)景。
分別是:
- 標(biāo)準(zhǔn)變量聲明(Variable declarations)。
- 簡(jiǎn)短變量聲明(Short variable declarations)
標(biāo)準(zhǔn)聲明
變量聲明創(chuàng)建了一個(gè)或多個(gè)變量,為它們綁定了相應(yīng)的標(biāo)識(shí)符,并給每個(gè)變量一個(gè)類型和初始值。
使用語法:
- 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, "腦子進(jìn)煎魚了"
- )
簡(jiǎn)短聲明
一個(gè)短變量聲明。使用語法:
- ShortVarDecl = IdentifierList ":=" ExpressionList .
案例代碼:
- s := "煎魚進(jìn)腦子了"
- i, j := 0, 10
- f := func() int { return 7 }
- ch := make(chan int)
- r, w, _ := os.Pipe()
- _, y, _ := coord(p)
網(wǎng)友疑惑
在我們?nèi)豪锏?Go 讀者提了這問題后,我也搜了搜相關(guān)資料。發(fā)現(xiàn)在 stackoverflow 上也有人提出了類似的疑惑:
問題是:使用哪一種聲明方式,令人困惑。
題主糾結(jié)的原因在于:
- 如果一個(gè)只是另一個(gè)的速記方式,為什么它們的行為會(huì)不同?
- Go 的作者出于什么考慮,讓兩種方式來聲明一個(gè)變量(為什么不把它們合并成一種方式)?只是為了迷惑我們?
- 有沒有其他方面需要我在使用時(shí)留心的,以防掉進(jìn)坑里?
下面我們結(jié)合 stackoverflow 的這個(gè)提問內(nèi)容和回答,進(jìn)一步展開,帶大家看看里面到底賣的是什么 “藥”。
先思考一下:標(biāo)準(zhǔn)聲明和短聲明,這兩者的區(qū)別的在哪那里,又或是憑喜好隨意使用?
區(qū)別在哪
代碼塊的分組聲明
使用包含關(guān)鍵字 var 的聲明語法時(shí),和其他 package、import、const、type、var 等關(guān)鍵字一樣,是可以進(jìn)行分組的代碼塊聲明的。
例如:
- var (
- i int
- u, v, s = 1.0, 2.0, "腦子進(jìn)煎魚了"
- )
而短聲明,是不支持的。
變量的初始值指定
使用標(biāo)準(zhǔn)的變量定義時(shí),我們可以只聲明,不主動(dòng)地定義該變量的初始值(缺省會(huì)給零值)。
例如:
- var (
- i int
- s string
- )
而短聲明則不行,必須要在程序中主動(dòng)地去對(duì)變量定義一個(gè)值。
例如:
s := "腦子進(jìn)煎魚了"
此處即使是定義的空字符串,那也屬于是用戶側(cè)主動(dòng)定義的,而非缺省的零值。
局部變量,區(qū)分作用域
在編寫程序時(shí),我們經(jīng)常會(huì)有一些局部變量聲明,且作用域是有限的。
可以看看自己的代碼,這種時(shí)候,我們都會(huì)采取短聲明的方式。
例如:
- for idx, value := range array {
- // Do something with index and value
- }
- if num := runtime.NumCPU(); num > 1 {
- fmt.Println("Multicore CPU, cores:", num)
- }
短聲明在這類場(chǎng)景下有明確的優(yōu)勢(shì),標(biāo)準(zhǔn)的變量聲明在這類場(chǎng)景不討好。
重新聲明變量
在 Go 語言規(guī)范中有明確提到,短變量聲明是可以重新聲明變量的,這是一個(gè)高頻重新聲明的覆蓋動(dòng)作。
如下:
- 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 變量就是不斷地被反復(fù)定義。在 if err != nil 猖狂的現(xiàn)在,短變量在此處的優(yōu)勢(shì),簡(jiǎn)直是大殺器了。
總結(jié)
相信很多小伙伴初入門時(shí)都為此糾結(jié)過一下,又或是很多教程壓根就沒有說清楚兩者變量聲明的區(qū)別。
在今天這篇文章中,我們介紹了 Go 的兩種變量聲明放水。并且針對(duì)短聲明存在的場(chǎng)景進(jìn)行了說明。
主要是:
- 代碼塊的分組聲明。
- 變量的初始值指定。
- 局部變量,區(qū)分作用域。
- 重新聲明變量。
你覺得變量聲明上,還有沒有別的優(yōu)缺點(diǎn)呢,歡迎在評(píng)論區(qū)交流:)
參考
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"?