GO學習筆記——GO語言變數與變數定義(5)
上一篇說完了GO語言的基本資料型別,這一篇就來說說怎麼定義各種不同型別的變數吧
GO語言中變數定義需要使用關鍵字var,並且GO語言中定義變數是和C++定義變數相反的,C++是變數型別在前,變數名在後;而GO是變數名在前,變數型別在後。這是它們之間在定義變數時最明顯的不同
1. 只宣告不定義
var a int
這個時候,又不一樣了。我們沒有給a變數初始化,那a的值到底是什麼呢?我們可以來看一下
func main() {
var a int
fmt.Println(a)
}
//輸出結果如下
0
Process finished with exit code 0
好像和C++不太一樣?C++中如果一個區域性變數只是宣告沒有初始化的話,那麼它會是一個隨機值。
GO語言有一個變數零值的概念,就是在只宣告而不賦值變數的時候,變數的值會預設給一個零值,這個零值不是隨機值。
- 數值型別(int,float32等)的零值都是0
- string的零值就是一個空字串
- bool的零值就是false
這幾個型別的零值需要記住。
func main() { var a int32 var b float32 var c bool var d complex64 var e string fmt.Println(a) fmt.Println(b) fmt.Println(c) fmt.Println(d) fmt.Printf("%q",e) //%q可以打出字串的引號,方便我們看 } //輸出結果如下 0 0 false (0+0i) ""
2. 對一個變數進行賦值
func main() {
var a int32
a = 5
fmt.Println(a,b,c)
}
3. 宣告和賦值同時進行
func main() {
var a int = 5
fmt.Println(a)
}
4. 分組宣告
func main() {
var (
a int = 5
b bool = true
c string = "pigff"
)
fmt.Println(a,b,c)
}
5. 同一行宣告多個變數並賦值(當然也可以不賦值)
func main() { var a,b,c int32 = 1,2,3 fmt.Println(a,b,c) }
如上,一次定義了三個變數a,b,c,順序給它們賦值為1,2,3
這裡有一個問題,如果我們給c賦值為3.1,也就是將一個浮點型別賦值給int32型別,會怎麼樣?
func main() {
var a,b,c int32 = 1,2,3.1
fmt.Println(a,b,c)
}
顯而易見會報錯
.\main.go:6:24: constant 3.1 truncated to integer
那麼,問題來了,這個int32在這邊不是很束縛手腳嗎,我一次要定義多個變數,但是我卻只能一次定義多個相同型別的變數,這很束縛我們的程式。
於是GO和其他很多程式語言一樣都這麼覺得,變數的型別我完全可以讓編譯器去自己推斷啊,比如3.1,編譯器就會自己給他推斷成浮點型而不會是int32,因此,我們完全可以省略這個束縛手腳的型別宣告。
func main() {
var a,b,c = 1,2,3.1
fmt.Println(a,b,c)
}
//輸出結果
1 2 3.1
再複雜編譯器都可以給我們推斷出來
func main() {
var a,b,c,d,e = 1,3.1,3+4i,true,"pigff"
fmt.Println(a,b,c,d,e)
}
//輸出結果
1 3.1 (3+4i) true pigff
那麼編譯給我們推斷的這些型別到底是什麼呢?我們可以來看一下
func main() {
var a,b,c,d,e = 1,3.1,3+4i,true,"pigff"
fmt.Print("a的型別是: ")
fmt.Println(reflect.TypeOf(a))
fmt.Print("b的型別是: ")
fmt.Println(reflect.TypeOf(b))
fmt.Print("c的型別是: ")
fmt.Println(reflect.TypeOf(c))
fmt.Print("d的型別是: ")
fmt.Println(reflect.TypeOf(d))
fmt.Print("e的型別是: ")
fmt.Println(reflect.TypeOf(e))
}
//輸出結果
a的型別是: int
b的型別是: float64
c的型別是: complex128
d的型別是: bool
e的型別是: string
- 編譯器推斷的整型是int,因為我們的機器是64位的,所以這個int表示的其實是int64
- 編譯器推斷的浮點型別是float64,因為我們的機器是64位的,而不是float32
- 編譯器推斷的複數型別是complex128,因為我們的機器是64位的,而不是complex64
- 編譯器直接推斷出true是bool型別
- 編譯器直接推斷出"pigff"是string型別
C++11中的auto關鍵字可以做到這一點,當然沒有GO這樣簡單,因為畢竟還要寫一個auto關鍵字,這也是GO語法簡單的一個表現
6.更加簡單的宣告且賦值寫法
我們可以把上面的賦值語句再簡單地改一下。
每次都要寫一個var關鍵字是不是很煩?我們可以在區域性變數中省略這個關鍵字。
注意如果這個變數是在函式體外定義的,那麼就必須要加上var關鍵字。也因此,下面的簡化寫法只用於在函式體內定義的區域性變數
func main() {
a,b,c,d,e := 1,3.1,3+4i,true,"pigff"
fmt.Println(a,b,c,d,e)
}
如上這樣是可以的,用 : 來簡化變數的定義,這個和使用var關鍵字的效果是一樣的。
但是一旦一個變數通過這樣來定義了,就不可以再使用:,因為這會是一個重複定義
func main() {
a := 1
a := 5
fmt.Println(a)
}
會報出如下的錯誤
.\main.go:9:4: no new variables on left side of :=
就像一開始說的,不能在函式體外這麼使用
import (
"fmt"
)
a := 1
func main() {
fmt.Println(a)
}
這個錯誤標記在了上面import的右括號上,但是實際還是錯在這個賦值語句
.\main.go:7:1: syntax error: non-declaration statement outside function body