Go 語言入門基礎學習筆記之 Go 語言的變量
變量#
Go 語言變量名由字母、數字、下劃線組成,其中首個字符不能為數字。
聲明變量的一般形式是使用 var
關鍵字:
var identifier type
可以一次聲明多個變量:
var identifier1, identifier2 type
Go 語言的習慣是將變量名稱放在前,數據類型放在後。
Go 語言聲明了一個變量就必須使用,否則會報錯。
單變量聲明#
- 指定變量類型
var v_name v_type
v_name = value
如果沒有初始化,則變量默認為零值
零值就是變量沒有做初始化時系統默認設置的值
- 數字類型的零值(包括 complex 64/128)為
0
- 布爾類型的零值為
false
- 字符串的零值為
""
(空字符串) - 其他幾種類型為
nil
:
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口
- 根據值自行判定變量類型
和 python 很像,不需要顯示聲明類型,自動推斷
var v_name = value
- 使用
:=
聲明變量
這種短變量聲明通常在函數內部使用,不能用於全局變量。
如果變量已經使用 var
聲明過,再使用 :=
聲明變量,就會產生編譯錯誤。
同理,變量使用 :=
進行聲明並賦值後,不能再次聲明。
var intVal int
intVal := 1
// 這時候會產生編譯錯誤,因為 intVal 已經聲明,不需要重新聲明
intVal := 1
相當於:
var intVal int
intVal = 1
// 或者
var intVal int = 1
多變量聲明#
- 非全局變量聲明
類型相同多個變量,一般使用這種方式聲明非全局變量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
- 根據值自行判定變量類型
和 python 很像,不需要顯示聲明類型,自動推斷。可以混合不同數據類型。
var vname1, vname2, vname3 = v1, v2, v3
- 使用
:=
聲明變量
出現在 :=
左側的變量不可以是已經被聲明過的,否則會導致編譯錯誤
這種不帶聲明格式的只能在函數中出現,可以混合不同數據類型。
vname1, vname2, vname3 := v1, v2, v3
- 全局變量聲明
這種因式分解關鍵字的寫法一般用於聲明全局變量。不初始化時為默認值。
var (
vname1 v_type1 = v1
vname2 v_type2
)
例子:
package main
import "fmt"
var x, y int
var ( // 這種因式分解關鍵字的寫法一般用於聲明全局變量
a int
b bool
)
var c, d int = 1, 2
var e, f = 123, "hello"
//這種不帶聲明格式的只能在函數體中出現
//g, h := 123, "hello"
func main(){
g, h := 123, "hello"
fmt.Println(x, y, a, b, c, d, e, f, g, h)
}
值類型和引用類型#
所有像 int、float、bool 和 string 這些基本類型都屬於值類型,使用這些類型的變量是直接指向存在內存中的值。
引用類型: slice、pointer、map、channel、function
當使用等號 =
將一個變量的值賦值給另一個變量時,如:j = i
,實際上是在內存中將 i
的值進行了拷貝
可以通過
&i
來獲取變量i
的內存地址,例如:0xf840000040
,每次的地址都可能不一樣。
值類型變量的值存儲在堆中。
內存地址會根據機器的不同而有所不同,甚至相同的程序在不同的機器上執行後也會有不同的內存地址。因為每台機器可能有不同的存儲器佈局,並且位置分配也可能不同。
更複雜的數據通常會需要使用多個字,這些數據一般使用引用類型保存。
一個引用類型的變量 r1
存儲的是 r1
的值所在的內存地址(數字),或內存地址中第一個字所在的位置。
這個內存地址稱之為指針,這個指針實際上也被存在另外的某一個值中。
同一個引用類型的指針指向的多個字可以是在連續的內存地址中(內存佈局是連續的),這也是計算效率最高的一種存儲形式。也可以將這些字分散存放在內存中,每個字都指示了下一個字所在的內存地址。
當使用賦值語句 r2 = r1
時,只有引用(地址)被複製。
如果 r1
的值被改變了,那麼這個值的所有引用都會指向被修改後的內容,在這個例子中,r2
也會受到影響。
注意事項#
簡短形式,使用 :=
賦值操作符
我們知道可以在變量的初始化時省略變量的類型而由系統自動推斷,聲明語句寫上 var
關鍵字其實是顯得有些多餘了,因此我們可以將它們簡寫為 a := 50
或 b := false
。
a 和 b 的類型(int 和 bool)將由編譯器自動推斷。
這是使用變量的首選形式,但是它只能被用在函數體內,而不可以用於全局變量的聲明與賦值。使用操作符 :=
可以高效地創建一個新的變量,稱之為初始化聲明。
在相同的代碼塊中,我們不可以重複對於相同名稱的變量使用初始化聲明,因為之前也說明過 :=
相當於聲明 + 賦值,編譯器會提示錯誤 no new variables on left side of :=
,但是 a = 20
是可以的,因為這是給相同的變量賦予一個新的值。
如果你在定義變量 a 之前使用它,則會得到編譯錯誤 undefined: a
如果你聲明了一個局部變量卻沒有在相同的代碼塊中使用它,同樣會得到編譯錯誤
package main
import "fmt"
func main() {
var a string = "abc"
fmt.Println("hello, world")
}
嘗試編譯這段代碼將得到錯誤 a declared but not used
。
因此,單純地給 a 賦值是不夠的,這個值必須被使用。但是全局變量是允許聲明卻不使用的
多個變量可以在同一行聲明和賦值。
var a, b int
var c string
a, b, c = 5, 7, "abc"
// 或者直接使用簡短形式
a, b, c := 5, 7, "abc"
右邊的這些值以相同的順序賦值給左邊的變量,這被稱為 並行 或 同時 賦值。
如果你想要交換兩個變量的值,則可以簡單地使用 a, b = b, a
,兩個變量的類型必須是相同。
空白標識符 _
也被用於拋棄值,如值 5
在 _, b = 5, 7
中被拋棄。
_
實際上是一個只寫變量,你不能得到它的值。這樣做是因為 Go 語言中你必須使用所有被聲明的變量,但有時你並不需要使用從一個函數得到的所有返回值。
並行賦值也被用於當一個函數返回多個返回值時。