GO學習筆記——數組(10)

今天來看看數組。C/C++還有其他一些語言基本都用方括號 [] 來表示數組,另外C++還有array數組容器以及vector動態順序表(這其實相當於後面要說到的切片)。

當然了,今天的主題是GO的數組。

GO也是用方括號 [] 來表示數組,先來看下它的一些定義方式

func main() {
	//1. 聲明瞭一個包含5個int的數組,每個元素被賦零值0
	var arr1 [5]int

	//2. 定義了一個包含5個int的數組,前三個元素分別被賦值爲1,2,3,後兩個元素被賦零值0
	arr2 := [5]int{1,2,3}

	//3. 用...來省略個數,這裏就是定義了一個包含5個int的數組,編譯器幫我們計算這個數組的大小
	arr3 := [...]int{1,2,3,4,5}

	//4. 定義一個四行五列的二維數組,且第一行被賦值爲全1
	arr4 := [4][5]int{{1,1,1,1,1}}

	fmt.Println(arr1)
	fmt.Println(arr2)
	fmt.Println(arr3)
	fmt.Println(arr4)
}
[0 0 0 0 0]
[1 2 3 0 0]
[1 2 3 4 5]
[[1 1 1 1 1] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

以上幾種定義方式是較爲常見的定義方式,總結一下

  • 遵循GO基本的變量命名規則,數組名現在前面,數組的元素類型寫在後面
  • 數組的元素個數寫在類型前面,用 [n]type 表示
  • []內可用...表示讓編譯器計算數組個數

下面來說一些數組使用的技巧


遍歷數組的range關鍵字

一般在C語言中,遍歷一個數組都是用類似如下的遍歷方式,GO語言中也是一樣

func main() {
	arr := [5]int{1,2,3,4,5}
	for i := 0; i < 5; i++ {
		fmt.Print(arr[i])
	}
}
//輸出結果
12345

 但是GO語言中有一個專門用於遍歷數組的關鍵字range,可以方便我們遍歷數組,用法如下

func main() {
	arr := [5]int{1,2,3,4,5}
	for i,v := range arr {
		fmt.Printf("第%d個元素是: %d\n",i,v)
	}
}

//輸出結果
第0個元素是: 1
第1個元素是: 2
第2個元素是: 3
第3個元素是: 4
第4個元素是: 5

這就有點類似於C++11中引入的範圍for循環了,其實很多語言都引入了這種類似的範圍for循環來簡化傳統for循環的寫法。

range返回兩個值,它返回的第一個參數是索引,第二個參數是該索引的值,所以我們可以像上面一樣用兩個變量來接收它們。

正式因爲range能夠同時返回索引以及索引的值的特性,所以在遍歷數組的時候,基本上都使用range來遍歷,方便直觀。

 

當然,這裏有一個問題,有時候我們只想要索引的值,而不想要該索引,那麼怎麼辦,那麼就可以使用下劃線_了。

func main() {
	//用下劃線來不接收索引,而只接收索引的值
	arr := [5]int{1,2,3,4,5}
	for _,v := range arr {
		fmt.Println(v)
	}
}

//輸出結果
1
2
3
4
5

如果只要索引,那麼就不用這麼麻煩了,直接用一個返回值來接收就可以了

func main() {
	//用下劃線來不接收索引,而只接收索引的值
	arr := [5]int{1,2,3,4,5}
	for i := range arr {
		fmt.Println(arr[i])
	}
}

//輸出結果
1
2
3
4
5

數組的長度

可以通過len函數來獲得數組的長度

func main() {
	arr := [5]int{1,2,3,4,5}
	fmt.Println(len(arr))
}

輸出結果

5

數組是值類型的

先上一段C++的代碼

#include <iostream>
using namespace std;

void func(int *arr){
    arr[0] = 100;    //這裏將數組的第一個元素改爲100
}
int main(){
    int arr[] = {1,2,3,4,5};
    func(arr);
    for(int i = 0; i < 5; ++i)
        cout << arr[i] << " ";
    cout << endl;
    return 0;
}

輸出結果

100 2 3 4 5 

可以看到,我們將這個數組作爲參數傳給了函數func,並在函數體內修改了第一個數組元素的值,我們發現函數執行完以後,原來的數組的第一個元素被改變了,這就是引用類型的。C++函數參數類型要傳數組的時候,會弱化成數組首元素的地址傳進去,也就是說,函數拿到的是原來的數組的首元素的地址,也就是一個指針,這樣進行改動,當然會改變原數組的值。

但是GO就不是了,GO的數組是值類型的。先把上述代碼改成GO版本的。

//注意下面必須是[5]int,GO編譯器認爲[3]int和[5]int是兩種不同的數據類型
func fun(arr [5]int){
	arr[0] = 100
}

func main() {
	arr := [5]int{1,2,3,4,5}
	fun(arr)
	for i := range arr {
		fmt.Printf("%d ",arr[i])
	}
}

輸出結果

1 2 3 4 5

這邊GO就沒有對元素進行改變,也就是說,在GO語言中,數組是值類型的。其實,在數組傳參的時候,因爲只有值傳遞,所以是拷貝了一個一模一樣的數組作爲臨時的參數傳給函數的,所以這是兩個數組,臨時數組改變不影響原來的數組。

那麼我要是想改變原來的數組內容怎麼辦呢?很簡單,用指針,傳參數的時候傳一個指針就好了。

//注意下面必須是[5]int,GO編譯器認爲[3]int和[5]int是兩種不同的數據類型

func fun(arr *[5]int){    //這裏傳一個指針
	arr[0] = 100
}

func main() {
	arr := [5]int{1,2,3,4,5}
	fun(&arr)    //這裏傳數組的的地址
	for i := range arr {
		fmt.Printf("%d ",arr[i])
	}
}

輸出結果

100 2 3 4 5 

可以看到,這樣原數組就被改變了。

所以,這裏關於數組給函數傳參的時候的用法,需要注意,到底是要傳值呢,還是要傳指針,需要根據程序來不同設計。

 

但是,這樣傳參數還是很麻煩啊,我們必須得提前知道數組的個數,因爲不同個數的數組是被認爲不同類型的。

所以在GO語言中一般不直接使用數組,而是使用切片,關於切片的部分,下一章再來講。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章