【go語言 基礎系列】陣列及slice
【陣列】
Go語言處理陣列特別的地方是:go把陣列看成是值傳遞
如果需要傳引用,需要額外處理 *[5]int
如下demo
package main import ( "fmt" ) func main() { var arr1 = [5]int{1, 2, 3, 4, 5} var arr2 = [5]int{1, 2, 3, 4, 5} fmt.Println("arr1 is:", arr1) dealarr(arr1) fmt.Println("arr1 is:", arr1) // *[5]int p fmt.Println("arr2 is:", arr2) dealp(&arr2) //通過& 來獲取指標傳遞引數 fmt.Println("arr2 is:", arr2) } func dealarr(a [5]int) { a[0] = 55 fmt.Println(" a is:", a) } func dealp(b *[5]int) { b[0] = 66 fmt.Println("b is", b) }
執行結果如下:
arr1 is: [1 2 3 4 5]
a is: [55 2 3 4 5]
arr1 is: [1 2 3 4 5]
arr2 is: [1 2 3 4 5]
b is &[66 2 3 4 5]
arr2 is: [66 2 3 4 5]
【slice】
slice的程式碼定義在runtime下的 slice.go中,其型別如下
type slice struct {
array unsafe.Pointer
len int
cap int
}
是一個有三個元素的struct
- array 為指標,指向陣列的可以從slice中訪問的第一個元素
- len 為長度,slice中元素的個數
- cap為容量,從slice的的起始元素(即指標)到底層陣列最後一個元素間的個數
檢測一個slice是否為空 使用len(slice1)==0.
更多demo如下
package main import ( "fmt" ) func main() { var arr = [10]string{"a1", "b2", "c3", "d4", "e5", "f6", "g7", "h8", "i9", "j10"} fmt.Printf("arr type is %T,\nvalue is %v\n", arr, arr) fmt.Println("len(arr) is:", len(arr)) s1 := arr[1:1] fmt.Println("s1: arr[1:1]", s1, "len is:", len(s1), "cap is:", cap(s1)) s2 := arr[2:5] fmt.Println("s2: arr[2:5]", s2, "len is:", len(s2), "cap is:", cap(s2)) s3 := arr[5:] fmt.Println("s3: arr[5:]", s3, "len is:", len(s3), "cap is:", cap(s3)) s4 := arr[:5] fmt.Println("s4: arr[:5]", s4, "len is:", len(s4), "cap is:", cap(s4)) s5 := arr[:] fmt.Println("s5: arr[:]", s5, "len is:", len(s5), "cap is:", cap(s5)) s6 := arr[7:8] fmt.Println("s6: arr[7:8]", s6, "len is:", len(s6), "cap is:", cap(s6)) s7 := arr[2:8] fmt.Println("s7 is: arr[2:8]", s7) //使用 range 來遍歷下標及value for i, j := range s7 { fmt.Println("i is", i, "j is:", j) } }
執行結果如下,可以體會出 len cap 及指標的實際意義。
arr type is [10]string,
value is [a1 b2 c3 d4 e5 f6 g7 h8 i9 j10]
len(arr) is: 10
s1: arr[1:1] [] len is: 0 cap is: 9
s2: arr[2:5] [c3 d4 e5] len is: 3 cap is: 8
s3: arr[5:] [f6 g7 h8 i9 j10] len is: 5 cap is: 5
s4: arr[:5] [a1 b2 c3 d4 e5] len is: 5 cap is: 10
s5: arr[:] [a1 b2 c3 d4 e5 f6 g7 h8 i9 j10] len is: 10 cap is: 10
s6: arr[7:8] [h8] len is: 1 cap is: 3
s7 is: arr[2:8] [c3 d4 e5 f6 g7 h8]
i is 0 j is: c3
i is 1 j is: d4
i is 2 j is: e5
i is 3 j is: f6
i is 4 j is: g7
i is 5 j is: h8
【陣列與slice】
slice依賴一個底層的陣列,下面的例子在同個底層陣列上建立了2 個slice,分別通過更改陣列的值,slice的值 來對比全域性的資料變化,最後演示了 append()內建函式的呼叫demo,可以看到 在slice中append資料,在容量允許的情況下會修改底層陣列的值。
package main
import (
"fmt"
)
func main() {
var arr1 = [10]string{"z0", "a1", "b2", "c3", "d4", "e5", "f6", "g7", "h8", "i9"}
slice1 := arr1[0:4]
slice2 := arr1[2:6]
//注意兩個slice中的共同元素
//注意元素個數與切片數值的管理
fmt.Println("slice1 arr1[0:4]:", slice1)
fmt.Println("slice2 arr1[2:6]:", slice2)
//直接修改底層陣列來看slice的變化
fmt.Println("arr1[2] is:", arr1[2])
arr1[2] = "BB22"
fmt.Println("arr1[2] is:", arr1[2])
fmt.Println("now arr1 is:", arr1)
fmt.Println("slice1 arr1[0:4]:", slice1)
fmt.Println("slice2 arr1[2:6]:", slice2)
//直接修改其中slice1的第四個元素
fmt.Println("slice1[3] is:", slice1[3])
slice1[3] = "Cnew"
fmt.Println("slice1[3] is:", slice1[3])
fmt.Println("### after change slice1[3]")
//修改slice1 後觀察底層陣列及 slice2的變化
fmt.Println("arr1 is:", arr1)
fmt.Println("slice1 arr1[0:4]:", slice1)
fmt.Println("slice2 arr1[2:6]:", slice2)
//append 對資料的影響
slicenew := append(slice1, "from_append")
fmt.Println("arr1 is:", arr1)
fmt.Println("slice1 arr1[0:4]:", slice1)
fmt.Println("slice2 arr1[2:6]:", slice2)
fmt.Println("slicenew is:", slicenew)
}
執行結果如下
slice1 arr1[0:4]: [z0 a1 b2 c3]
slice2 arr1[2:6]: [b2 c3 d4 e5]
arr1[2] is: b2
arr1[2] is: BB22
now arr1 is: [z0 a1 BB22 c3 d4 e5 f6 g7 h8 i9]
slice1 arr1[0:4]: [z0 a1 BB22 c3]
slice2 arr1[2:6]: [BB22 c3 d4 e5]
slice1[3] is: c3
slice1[3] is: Cnew
### after change slice1[3]
arr1 is: [z0 a1 BB22 Cnew d4 e5 f6 g7 h8 i9]
slice1 arr1[0:4]: [z0 a1 BB22 Cnew]
slice2 arr1[2:6]: [BB22 Cnew d4 e5]
arr1 is: [z0 a1 BB22 Cnew from_append e5 f6 g7 h8 i9]
slice1 arr1[0:4]: [z0 a1 BB22 Cnew]
slice2 arr1[2:6]: [BB22 Cnew from_append e5]
slicenew is: [z0 a1 BB22 Cnew from_append]