天天看點

十六、Go基礎程式設計:複合類型—切片slice2. 切片的建立3. 切片的操作4. 切片做函數參數 

1. 概述

數組的長度在定義之後無法再次修改;數組是值類型,每次傳遞都将産生一份副本。顯然這種資料結構無法完全滿足開發者的真實需求。Go語言提供了數組切片(slice)來彌補數組的不足。

切片并不是數組或數組指針,它通過内部指針和相關屬性引⽤數組⽚段,以實作變⻓⽅案。

slice并不是真正意義上的動态數組,而是一個引用類型。slice總是指向一個底層array,slice的聲明也可以像array一樣,隻是不需要長度。

十六、Go基礎程式設計:複合類型—切片slice2. 切片的建立3. 切片的操作4. 切片做函數參數 

2. 切片的建立

slice和數組的差別:聲明數組時,方括号内寫明了數組的長度或使用…自動計算長度,而聲明slice時,方括号内沒有任何字元

var s1 []int //聲明切片和聲明array一樣,隻是少了長度,此為空(nil)切片
    s2 := []int{}

    //make([]T, length, capacity) //capacity可以省略,則和length的值相同
    var s3 []int = make([]int, 0)
    s4 := make([]int, 0, 0)

    s5 := []int{1, 2, 3} //建立切片并初始化
           

3. 切片的操作

3.1 切片截取

十六、Go基礎程式設計:複合類型—切片slice2. 切片的建立3. 切片的操作4. 切片做函數參數 

示例說明:

十六、Go基礎程式設計:複合類型—切片slice2. 切片的建立3. 切片的操作4. 切片做函數參數 

3.2 切片和底層數組關系

s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

    s1 := s[2:5]       //[2 3 4]
    s1[2] = 100        //修改切片某個元素改變底層數組
    fmt.Println(s1, s) //[2 3 100] [0 1 2 3 100 5 6 7 8 9]

    s2 := s1[2:6] // 新切片依舊指向原底層數組 [100 5 6 7]
    s2[3] = 200
    fmt.Println(s2) //[100 5 6 200]

    fmt.Println(s) //[0 1 2 3 100 5 6 200 8 9]
           

3.3 内建函數

3.3.1 append

append函數向 slice 尾部添加資料,傳回新的 slice 對象:

var s1 []int //建立nil切換
    //s1 := make([]int, 0)
    s1 = append(s1, 1)       //追加1個元素
    s1 = append(s1, 2, 3)    //追加2個元素
    s1 = append(s1, 4, 5, 6) //追加3個元素
    fmt.Println(s1)          //[1 2 3 4 5 6]

    s2 := make([]int, 5)
    s2 = append(s2, 6)
    fmt.Println(s2) //[0 0 0 0 0 6]

    s3 := []int{1, 2, 3}
    s3 = append(s3, 4, 5)
    fmt.Println(s3)//[1 2 3 4 5]
           

append函數會智能地底層數組的容量增長,一旦超過原底層數組容量,通常以2倍容量重新配置設定底層數組,并複制原來的資料: 

func main() {
    s := make([]int, 0, 1)
    c := cap(s)
    for i := 0; i < 50; i++ {
        s = append(s, i)
        if n := cap(s); n > c {
            fmt.Printf("cap: %d -> %d\n", c, n)
            c = n
        }
    }
    /*
        cap: 1 -> 2
        cap: 2 -> 4
        cap: 4 -> 8
        cap: 8 -> 16
        cap: 16 -> 32
        cap: 32 -> 64
    */
}
           

3.3.2 copy

函數 copy 在兩個 slice 間複制資料,複制⻓度以 len 小的為準,兩個 slice 可指向同⼀底層數組。

data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    s1 := data[8:]  //{8, 9}
    s2 := data[:5] //{0, 1, 2, 3, 4}
    copy(s2, s1)    // dst:s2, src:s1

    fmt.Println(s2)   //[8 9 2 3 4]
    fmt.Println(data) //[8 9 2 3 4 5 6 7 8 9]
           

4. 切片做函數參數 

func test(s []int) { //切片做函數參數
    s[0] = -1
    fmt.Println("test : ")
    for i, v := range s {
        fmt.Printf("s[%d]=%d, ", i, v)
        //s[0]=-1, s[1]=1, s[2]=2, s[3]=3, s[4]=4, s[5]=5, s[6]=6, s[7]=7, s[8]=8, s[9]=9,
    }
    fmt.Println("\n")
}

func main() {
    slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    test(slice)

    fmt.Println("main : ")
    for i, v := range slice {
        fmt.Printf("slice[%d]=%d, ", i, v)
        //slice[0]=-1, slice[1]=1, slice[2]=2, slice[3]=3, slice[4]=4, slice[5]=5, slice[6]=6, slice[7]=7, slice[8]=8, slice[9]=9,
    }
    fmt.Println("\n")
}