1. 程式人生 > 實用技巧 >GO學習筆記(3)

GO學習筆記(3)

三. 切片(slice)

  切片:切片是陣列的一個引用,因此切片是引用型別;切片是可變陣列.

  3.1. 切片定義

// 建立切片 len()切片的長度 cap()切片的容量
func sliceCreate() {
    // 宣告 1
    var s1 []int
    fmt.Println(reflect.TypeOf(s1)) // 檢視型別: []int
    s2 := []string{}
    fmt.Println(reflect.TypeOf(s2)) // []string
    // 使用make宣告
    s3 := make([]int, 5, 8)
    fmt.Println(reflect.TypeOf(s3), s3, len(s3),cap(s3)) 
// []int [[0 0 0 0 0] 5 8 // 初始化 s4 := []int{1, 2, 3, 4, 5} fmt.Println(reflect.TypeOf(s4), s4, len(s4),cap(s4)) // []int [1 2 3 4 5] 5 5 // 從陣列中切片 arr := [8]int{1,2,3,4,5,6,7,8} fmt.Println(reflect.TypeOf(arr), len(arr),cap(arr)) // [8]int 8 8 // s5的容量為7,是因為切片只是把起始位置的指標向後移動到start位置,而end位置是保持不變的,以下同理 s5 :
= arr[1:4] fmt.Println(s5, len(s5),cap(s5)) // [2 3 4] 3 7 s6 := arr[:] fmt.Println(s6, len(s6),cap(s6)) // [1 2 3 4 5 6 7 8] 8 8 s7 := arr[2:] fmt.Println(s7, len(s7),cap(s7)) // [3 4 5 6 7 8] 6 6 s8 := arr[:3] fmt.Println(s8, len(s8),cap(s8)) // [1 2 3] 3 8 s9 := s6[1:3] fmt.Println(s9, len(s9),cap(s9))
// [2 3] 2 7 }

  3.2. 切片訪問以及追加

func sliceAtc() {
    // 可用指標直接訪問底層陣列
    s1 := make([]int, 5, 8)
    s1[1] = 2
    p := &s1[3]
    *p = 10
    s2 := s1[1:]
    s2[1] = 30
    fmt.Println(s1) // [0 2 30 10 0]

    // 可直接修改 struct array/slice 成員
    d := [5]struct {
        x int
    }{}
    s := d[:]
    d[1].x = 10
    s[2].x = 20
    fmt.Println(d) // [{0} {10} {20} {0} {0}]
    // s 時新開闢的空間,但是s指向的還是底層陣列d
    fmt.Printf("%p, %p, %p, %p\n", &s, &s[0], &d, &d[0]) // 0xc0000044e0, 0xc0000103c0, 0xc0000103c0, 0xc0000103c0

    // 想切片中新增元素 append()
    a := make([]int, 3, 5)
    // 追加一個元素後,容量在a.cap()範圍內,則底層陣列不變,返回的slice依然指向原底層陣列
    b := append(a, 1)
    fmt.Println(a, len(a), cap(a)) // [0 0 0] 3 5
    fmt.Println(b, len(b), cap(b)) // [0 0 0 1] 4 5

    // 超出b的容量,會重新分配底層陣列
    c := append(b, a...)
    fmt.Println(c, len(c), cap(c))   // [0 0 0 1 0 0 0] 7 10
    fmt.Println(&a[0], &b[0], &c[0]) // 0xc000010450 0xc000010450 0xc000014190
}