轉--Golang語言--複合資料
1、array
陣列的型別格式為單個數據單元型別+長度構成,如 [2]int,其中 [2] 代表陣列的長度,而 int 代表每個單元都是整形。
陣列的元素操作也是通過操作下標,即 arr[1] ,取出陣列 arr 中的第2個元素,陣列下標從0開始算起。
陣列的長度可以通過 len(arr) 獲取陣列 arr 的長度。
1-1 宣告和初始化
陣列宣告格式為 var 陣列名 [陣列長度]元素型別
例如:
var arr [2]int
arr[0] = 1 // 宣告以後,就可以使用index進行賦值
宣告陣列後,未進行初始化,則每個資料單元的初值是單元資料型別的預設值,例如 int 就是 0 ,string 是空 ""
宣告的同時也可以初始化
var arr [2]int = [2]int{1, 2}
初始化資料的格式為: 陣列型別 + 大括號 + 陣列的資料
也可以使用:=來縮寫
arr := [2]int{1, 2}
使用:=可以省略陣列長度,而使用 [...] 讓Go自動計算陣列長度
arr := [...]int{1, 2}
PS:Go中的 ... 在別的地方還有很多,通常代表的意思是編譯或執行時確定數目。
1-2 陣列的巢狀
陣列也可以作為另外一個數組的元素,這樣就形成多維陣列(巢狀陣列)
arr := [2][2]int{[2]int{1, 2}, [2]int{3, 4}}
可以簡寫為
arr := [2][2]int{{1, 2}, {3, 4}}
同樣巢狀陣列的同緯度下的元素型別必須一致,例如
var arr [2][2]int arr0 := [2]int{1, 2} arr[0] = arr0
arr1 := [1]int{1} arr[1] = arr1 // 編譯報錯:cannot use arr1 (type [1]int) as type [2]int in assignment
1-3 陣列的長度
陣列長度必須宣告時給出,一旦給出以後便不能發生改變,可以通過len函式來獲取陣列的長度
1-4 陣列的越界
如果下標小於0或者大於等於陣列的長度
a、下標是數值常量,則編譯報錯:index out of bounds
b、下標是動態變數,則執行的時候檢測,錯誤資訊是 runtime error : index out of range
1-5 陣列的賦值
array 賦值不同於 string , string 因為不能改變,所以只用傳字串的地址即可,而 array 因為能改變,所以要將整個內容複製,在記憶體中會有2份資料存在
arr1 := [2]int{1, 2} var arr2 [2]int
arr2 = arr1 arr2[1] = 3 fmt.Print(arr1[1]) // 輸出2
因為陣列賦值需要佔用空間,所以大多數情況是使用slice,用切片傳遞陣列的地址的方式來減小記憶體的消耗。
2、slice
slice可以認為是個特殊的類陣列的結構,其指向一個數組型別的資料,使用方式也同陣列,越界報同陣列一樣的錯誤
2-1 slice 的宣告
var s []int //不同於陣列,長度是不指明的,如果指明則是一個數組
宣告 slice 後,未進行初始化,則 slice 的值是 nil ,可以通過make進行預設值初始化,也可以使用具體值初始化。
預設值初始化(以下初始化都使用簡短格式:=)
s := make([]int, 4, 4) // 第一個4為切片的長度,第二個為切片的容量,下面有解釋
// 等同於 s := []int{0, 0, 0, 0}
具體值初始化的3種情況
a、指向已經存在的陣列
arr := [4]int{1, 2, 3, 4}
s := arr[1:3]
b、建立一個(匿名)陣列並且指向這個陣列
s := []int{1, 2, 3, 4}
c、基於另一個slice
s1 := []int{1, 2, 3, 4}
s2 := s1[2:4]
2-2 slice 的結構
slice 的結構包含3部分:指向底層資料(起始下標)的指標、長度、容量。
長度同陣列一樣,使用len函式,容量則用cap函式
Array_a := [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'} Slice_a := Array_a[2:5]
例子的結構如下圖所示(圖片來自https://github.com/astaxie/build-web-application-with-golang)
按照數學上區間定義理解就是,array[i:j]的區間應該是[i,j),即包含的元素索引是 i <= index < j
上例中的 Array_a[2:5] 則包含的元素是:Array_a[2],Array_a[3] ,Array_a[4]
Slice_a 的 len() 等於 j - i
Slice_a 的 cap() 等於 len(Array_a) - i
如果i為0,j為array的長度,則可以忽略
Slice_a := Array_a[:] // 則包含陣列的所有元素
2-3 slice的一些操作函式
除了上面已經說的make、len、cap函式之外,slice還支援append、copy操作函式
copy(dst, src) 從源src中複製元素到目標dst,並且返回複製的元素的個數,在Go語言中,幾乎都遵循這樣的次序,即目標引數在前,源引數再後
copy支援將string型別複製到位元組切片,除此之外都必須型別相同
var byte_slice = make([]byte, 2)
copy(byte_slice, "hi")
append(dst, src) 將源src追加到目標dst中,其中源src可以是一個或者多個單一型別的值
int_slice := []int{1}
int_slice = append(int_slice, 2, 3) // [1, 2, 3]
也可以使另外一個切片,但是切片後面需要指定...特殊標記
int_slice := []int{1}
int_slice2 := []int{2, 3} int_slice = append(int_slice, int_slice2...) // [1, 2, 3]
通樣append也支援將string型別複製到位元組切片,後面需要指定...特殊標記
var byte_slice = []byte("hello") byte_slice = append(byte_slice, "world"...)
2-4 slice 的一些快捷操作
//在i位置後插入元素x
slice = append(slice[:i], append([]T{x}, slice[i:]...)...) // T的意思代表是某個資料型別
//在i位置後插入切片
slice1 = append(slice[:i], append(slice2, slice[i:]...)...)
//在i位置後插入j個空元素
slice = append(slice[:i], append(make([]T, j), lice[i:]...)...)
//切片追加單個元素
slice = append(slice, x)
//切片追加切片內容
slice1 = append(slice1, slice2...)
//切片追加 j個空元素
slice = append(slice, make([]T, j)...)
//複製切片
slice2 = make([]T, len(slice1))
copy(slice2, slice1)
//刪除切片中的第i個元素
slice = append(slice[:i], slice[i+1:]...)
//刪除切片中的指定元素集合[i:j]
slice = append(slice[:i], slice[j:]...)
// 彈出第一個元素
x, slice = slice[0], slice[1:]
// 彈出最後一個元素
x, slice = slice[len(slice)-1], slice[:len(slice)-1]
3、map
map在一些語言中稱之為字典(Dictionary),也有稱之為散列表(Hash Table) ,指的是一些型別的值到另一個型別的值的對應關係。
3-1 宣告和初始化
map宣告格式為 var map名 map[索引型別]元素型別
例如:
var map1 map[int]string
宣告map後,未進行初始化,則map的值nil,還不能進行賦值,需要用make進行初始化
map1 = make(map[int]string)
宣告的同時也可以初始化
var map1 map[int]string = make(map[int]string)
也可以使用:=來縮寫
map1 := make(map[int]string)
也可以不用make,直接用值初始化
map1 := map[int]string{}
使用指定值初始化的時候,需要用key:value的格式
map1 := map[int]string{1:"1",2:"2"}
3-2 map操作
內建函式len通用可以用在map上,返回當前map中有多少個元素
map因為沒有記憶體限制,可以很方便的新增,也可以很方便的刪除,刪除需要用delete,例如刪除map1的key為1的元素為
delete(map1, 1)
獲取map中的key的value
v := map[key]
判斷是否存在某個key
v, ok := map[key]
key存在map中, v = key 的 value,ok = true
key不存在map中, v = T(default),ok = false
新增或者更改value
map[key] = value
注意 map 不保證 key - value 的存放順序
key必須是支援比較運算子(== !=)的型別,如number、string、pointer、array、struct 、interface(介面實現型別必須支援比較運算子),不能是function、map、slice