陣列
go語言中陣列的特點:
陣列的長度是固定的,並且長度也是陣列型別的一部分
是值型別,在賦值或者作為引數傳遞時,會複製整個陣列,而不是指標
定義陣列的語法:
var arr1 = [5]int{1,2} // [5]int{1, 2, 0, 0, 0} 未初始化的值,就預設初始化為該型別的預設值
var arr2 = [...]int{1,2,3} // [3]int{1,2,3} 長度可由初始化的元素個數確定
var arr3 = [5]int{1: 20, 4: 50} // 可使用索引來初始化,其他值仍然是對應型別的預設值
var arr4 = [2][3]int{{1,2,3}, {2,3,4}} // 多維陣列
陣列常用操作
訪問陣列元素
可以直接使用索引值訪問
遍歷陣列
var arr = [5]string{"hello", "a", "b", "world", "sss"}
// 這裡只接收一個值,那這個值就是索引值
for i := range arr {
fmt.Println(arr[i]);
}
// 接收兩個值,就分別是索引值 和 索引對應的陣列值
for i, v := range arr {
fmt.Println(i, v);
}
len 和 cap 方法都可以返回陣列長度,即元素數量
Slice - 切片
slice的底層是陣列,它通過內部指標和一些相關屬性來引用陣列片段,所以slice是可以變長的
slice的結構:
struct Slice {
byte* array;
uintgo len;
uintgo cap;
}
切片slice的特點:
- 引用型別.本身是結構體
- 屬性len表示內部儲存的元素數
- cap表示當前切片的容量
- 如果屬性slice == nil, 那麼len, cap 都應該為0
- 切片可以通過陣列來產生,也可以直接建立切片;對切片進行讀寫,實際上就是操作底層的陣列
// 通過陣列產出切片
var arr = [8]int{2,3,5,7,4,6,9,10}
var s1 = arr[1:5:6] // 語法 [start: end: max], 此時 len = end - start, cap = max-start
// 直接建立切片
var s2 = []int{2,4,7} // 注意這裡宣告的是切片,"[]"沒有數字,go會自動分配底層陣列
// 使用make動態建立切片
var s3 = make([]int, 6, 8) // 語法: make([]型別, len, cap); 可以省略cap,此時cap = len
// 通過切片建立新切片, 新切片仍然執行原陣列
var s4 = s1[1,2,3] // 與從陣列產生切片是相似的,不過要注意範圍
切片的常用操作
func append([]T, t …T) []T
從函式的簽名就可以看出,作用是向切片的尾部新增元素,可以一次新增多個值,返回新的切片,
⼀旦超出原 slice.cap 限制,就會重新分配底層陣列,即便原陣列並未填滿。
s5 := append(s4, 20)
func copy(dst, src []T) int
這個方法將型別為 T 的切片從源地址 src 拷貝到目標地址 dst,覆蓋 dst 的相關元素,並且返回拷貝的元素個數。
源地址和目標地址可能會有重疊。拷貝個數是 src 和 dst 的長度最小值。
具體還是得看例子
src := []int{1,2,3,4}
dst := []int{2,3,4}
num := copy(dst, src) // dst=[]int{1,2,3}, num=3
src2 := []int{1,2,3}
dst2 := [2,3,4,5]
num2 := copy(dst2, src2) // dst2=[]int{1,2,3,5}, num2=3
src3 := []int{1,2,4}
dst3 := []int{1,2,3,5}
num3 := copy(dst3, src3) // dst3=[]int{1,2,4,5} num3=3
len()和map()方法分別返回切片中的元素數量 和 切片的容量
map型別
map型別是一種叫雜湊表的資料結構,在python中叫字典,還稱為關聯陣列。它是一組無序鍵值對的集合。給定鍵可以快速的定位對應的值
特點:
- 引用型別
- 鍵必須是支援相等比較(== !=)的型別,例如: number,string,array,struct等等
- 值可以是任何型別
- 它可以動態伸縮,不存在限制
定義語法:
map[keyType]valueType{
key1: value1,
key2: value2,
...
}
// eg:
m := map[string]int{
"age": 10,
"month": 12,
"day": 7,
"num": 1, // 這裡最後一行必須加上逗號,要不然,就把 "}"放在這個一行
}
還可以使用 make 函式來定義一個map,有助於提升效能。因為事先申請⼀⼤塊記憶體,可避免後續操作時頻繁擴張。
語法:
// 這裡的 length 是map的初始容量,可以不加,不過在新增元素時會平凡擴張,影響效能
make(map[keyType][valueType][, length])
map型別的基本操作
訪問map中的值
可以使用 map[key] 直接訪問對應的值
eg:
var m = map[int]string{
1: "hello",
2: "world",
5: "你好",
}
// 迭代map
for k := range m {
fmt.Println(m[k]);
}
// 還可以直接獲得鍵和值
for k, v := range m {
fmt.Println(k, v)
}
測試鍵是否存在
我們很多時候都會使用到
// 這裡使用了初始化,如果key存在, ok就是true, _接收的第一的引數就是值
// 如果key不存在,ok就是false
if _, ok := m[key]; ok {
//...
}
刪除指定鍵值對
刪除鍵前,還可以先判斷鍵是否存在,如果鍵不存在會報錯
var m = map[int]string{
1: "hello",
2: "world",
5: "你好",
}
delete(m, 1) // 刪除鍵為1的鍵值對