1. 程式人生 > >GO學習筆記——GO語言變數與變數定義(5)

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