Go 專欄 | 變量和常量的聲明與賦值
上篇文章介紹了環(huán)境搭建,并完成了學(xué)習(xí) Go 的第一個(gè)程序 Hello World。這篇文章繼續(xù)學(xué)習(xí) Go 的基礎(chǔ)知識(shí),來(lái)看看變量,常量的聲明與賦值。
本文所有代碼基于 go1.16.6 編寫(xiě)。
變量
Go 編程的命名風(fēng)格更習(xí)慣使用「短名稱」和「駝峰式」的名稱,而且大小寫(xiě)敏感。
開(kāi)頭必須是字母或者下劃線,而且首字母是大寫(xiě)還是小寫(xiě)也是有特殊含義的。大寫(xiě)字母開(kāi)頭可以被包外引用,小寫(xiě)字母開(kāi)頭只能在包內(nèi)使用,這個(gè)會(huì)在以后的文章中繼續(xù)分享。
聲明
第一種使用關(guān)鍵字 var 聲明變量:
var name type = expression
和 C 語(yǔ)言正好相反,類型是跟在變量名后面的。說(shuō)實(shí)話,剛開(kāi)始寫(xiě) Go 代碼的時(shí)候還真有些不習(xí)慣。
類型和表達(dá)式可以省略一個(gè),但不能都省略。如果類型省略,則類型由初始化表達(dá)式?jīng)Q定;如果表達(dá)式省略,則初始化值為對(duì)應(yīng)類型的零值。
對(duì)于數(shù)字是 0,布爾值是 false,字符串是 "",接口和引用(slice,指針,map,通道,函數(shù))是 nil,對(duì)于數(shù)組或結(jié)構(gòu)體這樣的復(fù)合類型,零值是其所有元素或成員的零值。
// 沒(méi)有初始值,會(huì)賦默認(rèn)零值
var v1 int
var v2 string
var v3 bool
var v4 [10]int // 數(shù)組
var v5 []int // 數(shù)組切片
var v6 struct {
e int
}
var v7 *int // 指針
var v8 map[string]int // map,key 為 string 類型,value 為 int 類型
var v9 func(e int) int
fmt.Println(v1, v2, v3, v4, v5, v6, v7, v8, v9)
// 輸出
// 0 false [0 0 0 0 0 0 0 0 0 0] [] {0} <nil> map[] <nil>
所以在 Go 中是不存在未初始化的變量的。
聲明單個(gè)變量:
// 聲明單個(gè)變量
var a = "initial"
fmt.Println(a)
// 聲明布爾值變量
var d = true
fmt.Println(d)
一次聲明多個(gè)變量:
// 聲明多個(gè)變量
var b, c int = 1, 2
fmt.Println(b, c)
建議以組方式一次聲明多個(gè)變量:
// 以組的方式聲明多個(gè)變量
var (
b1, c1 int
b2, c2 = 3, 4
)
fmt.Println(b1, c1)
fmt.Println(b2, c2)
第二種方式是短變量聲明:
name := expression
使用 := 來(lái)聲明,Go 編譯器會(huì)自動(dòng)推斷變量類型。注意 := 和 = 的區(qū)別,前者是聲明并賦值,后者是賦值。
這種初始化方式非常方便,在局部變量的聲明和初始化時(shí)經(jīng)常使用。
舉個(gè)例子:
// 短變量聲明方式
f := "short"
fmt.Println(f)
多個(gè)變量:
// 聲明賦值多個(gè)變量
g, h := 5, "alwaysbeta"
fmt.Println(g, h)
有一點(diǎn)需要注意,多個(gè)變量聲明時(shí),最少有一個(gè)新變量,否則會(huì)報(bào)錯(cuò)。
var i int
// i := 100 // 報(bào)錯(cuò) no new variables on left side of :=
i, j := 100, 101 // 有新值 j,不報(bào)錯(cuò)
fmt.Println(i, j)
第三種使用內(nèi)置 new 函數(shù):
p := new(T)
初始化為類型 T 的零值,并返回其地址。
先說(shuō)一下如何獲取變量的地址,其實(shí)很簡(jiǎn)單,使用取地址符 & 即可。
聲明一個(gè)整型的變量,然后對(duì)其取地址:
// 指針
k := 6
l := &k // l 為整型指針,指向 k
fmt.Println(*l) // 輸出 6
*l = 7
fmt.Println(k) // 輸出 7
使用 new 函數(shù)聲明變量:
// 使用內(nèi)置函數(shù) new 聲明
var p = new(int)
fmt.Println(*p) // 輸出整型默認(rèn)值 0
*p = 8
fmt.Println(*p) // 輸出 8
再來(lái)看一個(gè)例子,下面兩個(gè)函數(shù)是等價(jià)的,唯一的區(qū)別就是使用 new 少聲明了一個(gè)中間變量。
func newInt() *int {
return new(int)
}
func newInt1() *int {
var p int
return &p
}
賦值
使用 = 來(lái)賦值:
舉例:
// 變量賦值
var m, n int
m = 9
n = 10
fmt.Println(m, n)
多重賦值:
// 變量賦值
var m, n int
m = 9
n = 10
m, n = n, m
fmt.Println(m, n)
這個(gè)特性真是很爽,想想在 C 語(yǔ)言中是不能這么做的,要實(shí)現(xiàn)相同的效果,必須要借助一個(gè)中間變量才行。
如果有不需要的變量,使用空標(biāo)識(shí)符 _ 來(lái)忽略,在 Go 語(yǔ)言中,如果聲明了變量而不使用,程序是會(huì)報(bào)錯(cuò)的。
// 空標(biāo)識(shí)符
r := [5]int{1, 2, 3, 4, 5}
for _, v := range r {
// fmt.Println(i, v)
// fmt.Println(v) // 定義 i 但不用會(huì)報(bào)錯(cuò) i declared but not used
fmt.Println(v) // 忽略索引
}
作用域
變量分為全局變量和局部變量,局部變量會(huì)覆蓋全局變量:
// 全局變量
var gg = "global"
func main() {
// 作用域
fmt.Println(gg) // 輸出 global
gg = "local"
fmt.Println(gg) // 輸出 local
}
使用流程控制語(yǔ)句時(shí),需要特殊注意變量的作用域:
// 條件分支下的作用域
if f, err := os.Open("./00_hello.go"); err != nil {
fmt.Println(err)
}
f.Close() // 報(bào)錯(cuò) f.Close undefined (type string has no field or method Close)
正確的寫(xiě)法:
// 正確寫(xiě)法
file, err := os.Open("00_hello.go")
if err != nil {
fmt.Println(err)
}
file.Close()
常量
常量表示在程序運(yùn)行過(guò)程中恒定不變的值。
聲明
使用關(guān)鍵字 const 來(lái)聲明,語(yǔ)法和變量類似。
一般在給常量起名的時(shí)候,會(huì)起一個(gè)有明確含義的名字。
const Pi float64 = 3.14159265358979323846
聲明單個(gè)常量:
// 無(wú)類型整型常量
const n = 500000000
// 用編譯階段即可計(jì)算出值的表達(dá)式來(lái)賦值
const d = 3e20 / n
fmt.Println(d)
// 無(wú)類型浮點(diǎn)常量
const zero = 0.0
聲明多個(gè)常量
// 無(wú)類型整型和字符串常量
const a, b, c = 3, 4, "foo"
fmt.Println(a, b, c)
// 多個(gè)常量
const (
size int64 = 1024
eof = -1 // 無(wú)類型整型常量
)
fmt.Println(size, eof)
iota
常量聲明還有可以使用常量生成器 iota,它不會(huì)顯示寫(xiě)出常量的值,而是從 0 開(kāi)始,逐項(xiàng)加 1。
// 從 0 值開(kāi)始,逐項(xiàng)加 1
const (
a0 = iota // 0
a1 = iota // 1
a2 = iota // 2
)
fmt.Println(a0, a1, a2)
// 簡(jiǎn)寫(xiě),表達(dá)式相同,可以省略后面的
const (
b0 = iota // 0
b1 // 1
b2 // 2
)
fmt.Println(b0, b1, b2)
const (
b = iota // 0
c float32 = iota * 10 // 10
d = iota // 2
)
fmt.Println(b, c, d)
iota 在每個(gè) const 開(kāi)頭被重置為 0。
// iota 在每個(gè) const 開(kāi)頭被重置為 0
const x = iota // 0
fmt.Println(x)
// 同上
const y = iota // 0
fmt.Println(y)
還可以用來(lái)作為枚舉類型,比如一周 7 天,每天用一個(gè)數(shù)字表示,那么可以這么聲明:
// 枚舉
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
fmt.Println(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday)
總結(jié)
本文主要介紹了變量和常量的聲明和賦值,變量聲明主要有三種方式:
使用關(guān)鍵字
var來(lái)聲明;使用
:=的短變量聲明方式;使用內(nèi)置函數(shù)
new。
其中短變量方式在聲明局部變量時(shí)經(jīng)常使用,而且還要注意不要和賦值 = 弄混。
常量聲明和變量類似,只需要把 var 換成 const 即可。
常量還有一種特殊的聲明方式,使用 iota。它不會(huì)顯示寫(xiě)出常量的值,而是從 0 開(kāi)始,逐項(xiàng)加 1。
變量的作用域分為全局變量和局部變量,局部變量可以覆蓋全局變量,使用時(shí)需要注意。
文章中的腦圖和源碼都上傳到了 GitHub,有需要的同學(xué)可自行下載。
地址: https://github.com/yongxinz/gopher/tree/main/sc
關(guān)注公眾號(hào) AlwaysBeta,回復(fù)「goebook」領(lǐng)取 Go 編程經(jīng)典書(shū)籍。
Go 專欄文章列表:
