Go 語言的變量與常量
變量
go 語言的變量聲明和大多數(shù)語言類似,通過 var 關(guān)鍵字聲明變量,只是 go 語言作為靜態(tài)類型語言,聲明變量時需要指定其類型。
下面的代碼表示聲明一個『name』變量,類型為『string』,并給其賦值『"Shenfq"』。
var?name?string?=?"Shenfq"
如果我們不進行賦值,這變量會獲得一個默認值,下面列舉一些 go 語言中的基礎(chǔ)類型及其默認值。
| 類型 | 默認值 |
|---|---|
| int(int32、int64……) | 0 |
| uint(uint32、uint64……) | 0 |
| float32、float64 | 0.0 |
| bool | false |
| string | "" |
多變量聲明
上面介紹 go 語言通過 var 關(guān)鍵字進行單個變量聲明,我們還可以通過 var 關(guān)鍵字進行多個變量的聲明:
//?聲明兩個變量為同一類型
var?firstName,?lastName?string
//?給兩個變量同時賦值
firstName,?lastName?=?"frank",?"shen"
//?聲明兩個變量為不同類型
var?(
??age?int
?name?string
)
//?給兩個變量同時賦值
age,?name?=?25,?"Shenfq"
類型推導(dǎo)
如果我們在變量聲明階段,對變量進行了賦值操作,這時候我們是可以直接省略變量類型的,因為 go 在編譯過程中會依據(jù)所賦予的初始值推導(dǎo)出其類型。
var?age?=?25
fmt.Printf("age 類型為:%T",?age)?// age 類型為:int
var?(
??age?=?18
??name?=?"Shenfq"
)
fmt.Printf("age 類型為:%T",?age)?// age 類型為:int
fmt.Printf("name 類型為:%T",?name)?// name 類型為:string
簡短格式
前面介紹了變量聲明的時候,如果給定了初始值,go 在編譯階段可以進行類型推導(dǎo)。這種情況,go 提供了一種更簡單的聲明方式,通過 := 的方式進行變量聲明,可以省略 var 關(guān)鍵字。
func?main()?{
??age?:=?25
?name?:=?"Shenfq"
}
//?也可以進行多個變量同時賦值
func?main()?{
??age,?name?:=?25,?"Shenfq"
}
??注意事項一
這種聲明方式只能用于函數(shù)體內(nèi),不能用于全局變量的聲明。
//????不能在全局使用這種方式聲明變量
age,?name?:=?25,?"Shenfq"
//?只能在函數(shù)體內(nèi)使用該方式
func?main()?{
?age,?name?:=?25,?"Shenfq"
?fmt.Printf("age 類型為:%T",?age)
?fmt.Printf("name 類型為:%T",?name)
}
warning??注意事項二
已經(jīng)聲明過的變量,不能使用 := 的方式進行賦值。
func?main()?{
??var?age?int
?age?:=?25
}

已經(jīng)聲明過的變量,只能通過 = 的方式進行賦值。
func?main()?{
??var?age?int
?age?=?25
}
全局變量與局部變量
簡單來說,聲明在函數(shù)體外的變量為全局變量,聲明在函數(shù)體內(nèi)的變量為局部變量。
局部變量如果有聲明,沒有進行使用,則不會通過編譯。
func?main()?{
??var?age?int
}

但是,全局變量是可以聲明而不使用的。
var?age?int
func?main()?{
?name?:=?"Shenfq"
?//fmt.Printf("age 類型為:%T", age)
?fmt.Printf("name 類型為:%T",?name)
}
上面的代碼中,我們聲明了 age 全局變量,但是并未使用,可以正常編譯。
空白標識符
前面介紹過,go 在變量賦值的時候,可以一次性對多個變量賦值。同時,go 的函數(shù)在 return 的時候,也能一次返回多個結(jié)果。
func?double(num?int)?(string,?int)?{
?var?err?string
?if?num?<?0?{
??err?=?"num?不能為負數(shù)"
??return?err,?-1
?}
?result?:=?num?*?2
?return?err,?result
}
上面我們實現(xiàn)了一個 double 函數(shù),該函數(shù)接受一個 int 類型的變量(num),返回兩個值,一個為異常提示(string 類型),一個為 num * 2 的結(jié)果。如果 num < 0 , 則提示 num 不能負數(shù)。
func?main()?{
?err,?res?:=?double(10)
?if?err?!=?""?{
??fmt.Printf(err)
?}?else?{
??fmt.Printf("結(jié)果為:%v",?res)
?}
}
如果,我們并不關(guān)心 err ,只想執(zhí)行 double 之后,輸出其結(jié)果。
func?main()?{
?err,?res?:=?double(10)
?fmt.Printf("結(jié)果為:%v",?res)
}

運行后,我們會收到一個編譯錯誤,err 變量并未使用。這時候,就需要用到空白標識符(_)。
func?main()?{
?_,?res?:=?double(10)
?fmt.Printf("結(jié)果為:%v",?res)
}
我們可以通過 _ 來接受 err 值,這個地方的值就會被拋棄掉,就能順利通過編譯。
常量
常量就是不會發(fā)生變化的變量,一旦聲明就不會改變。go 語言中,常量的聲明只需要將變量聲明時的 var 關(guān)鍵字替換為 const 關(guān)鍵字。
//?隱式類型定義
const?PI?=?3.14
//?顯式類型定義
const?PI2?float??=?3.14
多常量聲明
與變量類似,常量也支持一次性聲明多個。
func?main()?{
?const?(
??PI?=?3.14
??PI2?=?3.14
?)
?fmt.Printf("結(jié)果為:%v\n",?PI)
?fmt.Printf("結(jié)果為:%v\n",?PI2)
}

如果一次聲明多個常量時,某個常量如果為進行賦值,默認會與上一個常量的值進行同步。下面代碼的運行結(jié)果,與上面的代碼一致。
func?main()?{
?const?(
??PI?=?3.14
??PI2
?)
?fmt.Printf("結(jié)果為:%v\n",?PI)
?fmt.Printf("結(jié)果為:%v\n",?PI2)
}
特殊常量
有個叫做 iota 的特殊常量,在常量的賦值過程中,會進行累加。
func?main()?{
?const?(
??A?=?iota
??B
??C
?)
?fmt.Println(A,?B,?C)?//?0?1?2
}
在 iota 累加的過程中,可以對其進行打斷。
func?main()?{
?const?(
??A?=?iota
??B
??C?=?"Shenfq"
????D
????E
?)
?fmt.Println(A,?B,?C,?D,?E)
}
這時候輸出的結(jié)果為:

這是由于我們將常量 C 修改為了字符串 "Shenfq",常量 D、E 會默認與上一條常量保持同步,所以會得到上述結(jié)果。但是, iota ?是支持重新恢復(fù)累加,只需要在指定位置重新賦值一次 iota 即可。
func?main()?{
?const?(
??A?=?iota
??B
??C?=?"Shenfq"
??D?=?iota?//?恢復(fù)累加狀態(tài)
??E
?)
?fmt.Println(A,?B,?C,?D,?E)
}
由于 C 占用了原本 2 的位置,所以 D 恢復(fù)后,也是從 3 開始的。

iota 這種累加的特性,特別像我們在其他語言中使用的枚舉,所以在 go 語言中,我們可以直接將 iota 當做枚舉來使用。
type?ButtonType?int
const?(
??Default?ButtonType?=?iota
??Primary
??Warning
??Error
)
