Golang 入门资料+笔记

《GO语言圣经》学习笔记(四)切片

2020-07-27  本文已影响0人  半亩房顶

切片实现原理

切片,则是由一个指向数组的指针,切片的长度和容量两个int组成

切片的长度就是它所包含的元素个数。
切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。

切片内存分配

区分空切片和nil切片

nil切片
空切片

一個零值的slice等於nil。一個nil值的slice併沒有底層數組。一個nil值的slice的長度和容量都是0,但是也有非nil值的slice的長度和容量也是0的,例如[]int{}或make([]int, 3)[3:]。與任意類型的nil值一樣,我們可以用[]int(nil)類型轉換表達式來生成一個對應類型slice的nil值。

var s []int    // len(s) == 0, s == nil
s = nil        // len(s) == 0, s == nil
s = []int(nil) // len(s) == 0, s == nil
s = []int{}    // len(s) == 0, s != nil

如果你需要測試一個slice是否是空的,使用len(s) == 0來判斷,而不應該用s == nil來判斷。除了和nil相等比較外,一個nil值的slice的行爲和其它任意0産長度的slice一樣;例如reverse(nil)也是安全的。除了文檔已經明確説明的地方,所有的Go語言函數應該以相同的方式對待nil值的slice和0長度的slice。

內置的make函數創建一個指定元素類型、長度和容量的slice。容量部分可以省略,在這種情況下,容量將等於長度。

make([]T, len)
make([]T, len, cap) // same as make([]T, cap)[:len]

在底層,make創建了一個匿名的數組變量,然後返迴一個slice;隻有通過返迴的slice才能引用底層匿名的數組變量。在第一種語句中,slice是整個數組的view。在第二個語句中,slice隻引用了底層數組的前len個元素,但是容量將包含整個的數組。額外的元素是留給未來的增長用的。

切片的扩容原理

go中数组不可扩容,跳过不做讨论。slice扩容规则如下:

package main

import (
    "fmt"
)

func main() {
    arr := [4]int{10, 20, 30, 40}
    slice := arr[0:2]
    testSlice1 := slice
    testSlice2 := append(append(append(slice, 1), 2), 3)
    slice[0] = 11

    fmt.Println(testSlice1[0])
    fmt.Println(testSlice2[0])
}

根据第二条规则,append三个元素后,slice超出了原本的arr的长度,已经变成了一个新的切片,所以slice[0]=11不再能影响testSlice2,输出结果:

11
10

更新slice变量不仅对调用append函数是必要的,实际上对任何可能导致长度、容量或底层数组变化的操作都是必要的

引用


欢迎大家关注我的公众号


半亩房顶
上一篇 下一篇

猜你喜欢

热点阅读