golang學習筆記--切片slice 與數組 arr

因爲我是寫php的,剛開始寫go的時候老是被數組坑。因爲在go中的數組是固定長度,所以會存在越界的時候。而在go中也很少直接使用數組。更多的時候會使用slice(切片)。

數組

數組是一個由固定長度的特定類型元素組成的序列,一個數組可以由零個或多個元素組成。數組的長度是固定的。和數組對應的類型是Slice(切片),它是可以增長和收縮動態序列,slice功能也更靈活,但是要理解slice工作原理的話需要先理解數組。

數組的聲明,需要指出數組內部元素類型,以及數組的長度

var  name [len]type

如:聲明一個長度爲5的Int 類型數組

var numbers [5]int

數組元素的訪問也是跟大多數語言一樣,可以通過索引下標來訪問,索引下標的範圍是從0開始到數組長度減1的位置。內置的len函數將返回數組中元素的個數。
下面是一些數組的簡單操作

func main() {
    var arr [3]int //聲明一個長度爲3的數組
    //往數組中增加元素
    arr[0] = 1
    arr[1] = 2
    arr[2] = 3
    // arr[3] = 1  這裏就會產生錯誤

    //在聲明數組的時候複製
    var addArr = [3]int{1, 2, 3}
    fmt.Println(addArr[0]) //

    moreArr := [...]int{1, 2} //這裏...表示不確定長度。最終數組的長度由實際的元素個數確認
    fmt.Println(moreArr[0])   //

    //數組的使用
    for k, v := range arr {
        fmt.Printf("第%d個元素爲%d\n", k+1, v)
    }

}

切片

slice是一個輕量級的數據結構,提供了訪問數組子序列(或者全部)元素的功能,slice的底層引用了一個數組對象。一個slice由三個部分構成:指針、長度和容量。指針指向第一個slice元素對應的底層數組元素的地址,要注意的是slice的第一個元素並不一定就是數組的第一個元素。長度對應slice中元素的數目;長度不能超過容量,容量一般是從slice的開始位置到底層數據的結尾位置。
func main() {
    arr := [5]int{1, 2, 3, 4, 5} //定義一個數組
    sle1 := arr[0:2]             //切片1
    sle2 := arr[1:3]             //切片2
    sle1[0] = 9                  //現在改變第一個切片的第一個元素
    fmt.Println(arr)             //[9 2 3 4 5]
    fmt.Println(sle1)            //[9 2]
    fmt.Println(sle2)            //[2 3]

    /**
     * 現在改變兩個切片共有的元素,通過結果可以看到
     * 底層數組 以及sle2中的一個元素都以及被改變了。
     * 可以很好的說明 切片是對數組的引用。兩個切片實際引用的是同一個底層數組
     *
     */
    sle1[1] = 10

    fmt.Println(arr)  //[9 10 3 4 5]
    fmt.Println(sle1) //[9 10]
    fmt.Println(sle2) //[10 3]

}

上面的例子說明切片的第一個構成部分是指向底層數組的指針,下面來看看容量跟長度。
內置的len和cap函數分別返回slice的長度和容量。

func main() {

    arr := [5]int{1, 2, 3, 4, 5}
    sli := arr[:4] // [1,2]
    fmt.Printf("切片長度爲%d,容量爲%d\n", len(sli), cap(sli))
   //切片長度爲4,容量爲5
    sl2 := arr[:2] // [1,2]
    fmt.Printf("切片長度爲%d,容量爲%d\n", len(sl2), cap(sl2)) 
    //切片長度爲2,容量爲5

     sl3 := sli[:6] //這裏會產生panic range of index。因爲超過源切片的容量

}

這裏我們可以看到,如果切片操作超出cap(s)的上限將導致一個panic異常,但是超出len(s)則是意味着擴展了slice,因爲新slice的長度會變大。那麼我們應該怎麼去給切片擴容呢,這裏我們需要用到append方法、看下面的例子

func main() {
    /**
     * 這裏使用make 創建一個切片  
      * make([]T, len, cap) 其中cap可以省略。默認爲Len
     */
    sli := make([]int, 1, 1) 

    fmt.Printf("切片長度爲%d,容量爲%d\n", len(sli), cap(sli)) //2
    for i := 1; i < 5; i++ {
        sli = append(sli, 2)
        fmt.Printf("切片長度爲%d,容量爲%d\n", len(sli), cap(sli)) //2
    }

}
輸出結果
切片長度爲1,容量爲1,地址爲0xc00005a420
切片長度爲2,容量爲2,地址爲0xc00005a420
切片長度爲3,容量爲4,地址爲0xc00005a420
切片長度爲4,容量爲4,地址爲0xc00005a420
切片長度爲5,容量爲8,地址爲0xc00005a420

通過上面例子可以看出,當切片長度大於當前容量的時候,會爲當前切片自動擴容。每次擴容的大小爲當前容量的2倍

數組跟切片的基本就到這了,下一篇我會寫一些切片的應用。還沒有入門,學習中。有錯誤的地方歡迎指出。

bVbvvx4?w=258&h=258

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章