1、數組
數組長度定義後不可修改,通過內置函數len()來獲取數組元素個數
1)類型
//長度爲32的byte數組,每個元素爲一個字節
[32]byte
//長度爲2*N的複雜類型數組
[2*N] struct{x,y int32}
//長度100的指針數組
[100]*float64
//二維數組,等同於[2]([3]int)
[2][3]int
//三維數組
[2][2][2]float64
2)定義
//定義一個長度爲5的數組,默認會使用int類型的零值(0)進行初始化
arr := [5]int{}
//與上面一句作用一樣
var arr [5]int = [5]int{}
//定義一個長度爲5的數組,其中arr[0]將被初始化爲1,其餘依舊是0
arr := [5]int{1}
//定義一個長度爲5的數組,其中arr[0]、arr[4]將被初始化爲1,其餘依舊是0
arr := [5]int{0:1,4:1}
//定義一個長度爲5的數組,默認會使用int類型的零值(0)進行初始化
arr := new([5]int)
//定義並初始化一個數組,這裏會自動推斷數組長度([...]起的作用),這裏需要跟後面切片定義的不同(沒有...)
arr := [...]int{1, 2, 3, 4, 5}
//定義並初始化一個數組,並且會自動推斷長度爲5,arr[4]將被初始化爲1,其餘依舊是0
arr := [...]int{4:5}
3)遍歷
//與其它編程語言類型的遍歷方式
//獲取數組arr的長度
lenth := len(arr)
for i := 0; i < lenth; i++ {
//使用數組索引方式遍歷數組
fmt.Print(arr[i], " ")
}
//使用range方式遍歷數組,range有兩個返回值,1爲索引,2爲值
for i, v := range arr {
fmt.Print("[",i,"]=",v, " ")
}
4)比較操作
在兩個數據是同一類型(長度及元素類型)時,可以使用==與!=對兩個數組進行比較,但不能使用<或>。
注:Go語言中數組是一個值類型,所有值類型變量在賦值和作爲參數傳遞時都將產生一次複製動作,
傳入函數中的數組僅是該數組的一個副本,因此就無法對其進行修改,如果此時的數組較大時,
將會降低程序的效率,關於這種場景的解決,下面的切片會進行講解。
2、切片
在上面我們提到數組兩個特點:
1、數據長度在定義後無法再次進行修改;
2、數據是值類型,每次傳遞都將產生一個副本;
而Slice(切片)正是爲解決以上兩個問題而存在。
從表象看,切片是一個指向原始數組的指針,但實際上,切片擁有自己的數據結構
1、一個指向原生數組的指針
2、數組切片中的元素個數
3、數組切片已分配的存儲空間
這裏需要區分兩個概念,
長度:切片已使用的大小,從切片頭開始算起,使用內置函數len()獲取
容量:切片允許使用的大小,從切片頭開始算起,至底層數組末尾,使用內置函數cap()獲取,
當切片長度超過容量時,會重新分配一個原容量兩倍的容間,並將值複製過去,與Java
中的ArrayList有點類似,要注意擴容後的內存地址與原內存地址不一樣。
1)定義
//此處先定義一個數組
arr := [5]int{}
//基於上面定義的數據定義一個指向arr索引值在[0,5)範圍(左開右閉)的切片
//這裏的[m,n]還可以有多種寫法,如[:5]表示[0,5),[1:]表示[1,len(arr)),[:]表示[0,len(arr))
arrSlice := arr[0:5]
//定義一個長度爲5,容量也爲5的切片,這裏要注意跟上面數組定義的差別,數組定義時中括號中有...
arrSlice := []int{1,2,3,4,5}
//定義一個長度爲5,容量也爲5的切片
mySlice := make([]int,5)
//定義一個長度爲5,容量爲10的切片
mySlice := make([]int,5,10)
//在切片上再切片,這種情況又叫做reslice,這裏的[m:n]必須滿足0<=m<n<=cap(mySlice)-m
mySlice2 := mySlice[:]
在reslice的情況下,有很多地方需要注意,因爲原slice與reslice實際底層使用的是同一塊內存
空間,當兩個的長度都在底層數組的長度內時,兩者共享的都是同一塊容間,當有一個超過之後,
這種情況將會被打破。如下面的代碼所示:
mySlice := make([]int,5,6)
//即mySlice[1]對應mySlice2[1],以此類推
mySlice2 := mySlice[1:]
//這裏相當於同時也對mySlice2[0]的值進行了修改
mySlice[1] = 10
//append爲內置函數,表示給切片追加值,mySlice長度增加了,但mySlice2長度依舊不變
mySlice = append(mySlice,1)
//這裏將會把mySlice[5]的值覆蓋爲2,即覆蓋上一句代碼的值
mySlice2 = append(mySlice2,2)
//經過上面代碼,已經用完所有空間,再添加值時,將會發生空間分配
mySlice2 = append(mySlice2, 7)
//這裏僅改變了mySlice2[0],而mySlice[1]不變
mySlice2[0] = -1
2)遍歷與數組遍歷一樣,這裏就不復述了
3)切片的增減
//在切片末尾添加值 1 ,如果超過容量,會導致重新分配容間,容量會是原容量的2倍
mySlice = append(mySlice,1)
//在切片末尾同是添加多個值
mySlice = append(mySlice,1,2,3)
//在切片末尾追加一個數組,這裏的"..."是必需的,否則會編譯錯誤,表示把數組打散後傳入
mySlice = append(mySlice,arr...)
//在切片末尾添加另一個切片,這裏mySlice2後的[:]被省略了
mySlice = append(mySlice,mySlice2...)
//切片的減,這裏表示刪除掉了mySlice[1],切片的長度減小,但容量不變
mySlice = append(mySlice[:1],mySlice[2:]...)
//切片的減,如果是要刪除切片末尾的話,則可以使用reslice的方式爲實現
mySlice = mySlice[0 : len(mySlice)-1]
4)內容複製
用於將內容從一個數組切片複製到另一個數組切片。
如果兩個切片不一樣大,將以較小切片的元素個數進行復制
//這裏要注意順序,與Java的那種前者from後者to相反
copy(targetSlice,sourceSlice)
3、map
未排序的鍵值對集合,系統直接內置,無需引入其它包
1)聲明
var 變量名 map[鍵類型]值類型
var myMap map[int]string
2)創建
//創建一個key爲int,值爲string的map,myMap需要先聲明
myMap = make(map[int]string)
//聲明+創建
myMap := make(map[int]string)
//創建一個容量爲100的map
myMap = make(map[int]string,100)
//聲明+創建
myMap = map[int]string{}
//聲明+創建+初始化
myMap = map[int]string{1: "1"}
3)元素賦值、刪除、查找
//增加或修改key=123對應的元素值爲字符型"123"
myMap[123] = "123"
//刪除key=123對應的元素
delete(myMap,123)
//查找key=123對應的元素,該操作有兩個返回值,多返回值知識點將在函數相關內容說到,
//返回值1爲對應的值,返回值2爲是否包含該key
v, ok := myMap[123]
本文介紹了編程中最常用的兩種數據結構,數組及map,同時介紹了一種可伸縮的”數組”又可以看作爲一個數組指針–切片,數組與切片有太多相似的地方,但同時又存在差異,所以做爲新手要特別注意。
無聞(unknow)《Go編程基礎》
許式偉的 《Go語言編程》