Go 切片操作


前言

go語言中的切片,可以看作是可變化長度的數組(動態數組)。有長度(len)和容量(cap),容量必大於等於長度。

切片的結構體定義如下:

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

 

切片的定義方式

var (
    a []int               // nil切片, 和 nil 相等, 一般用來表示一個不存在的切片
    b = []int{}           // 空切片, 和 nil 不相等, 一般用來表示一個空的集合
    c = []int{1, 2, 3}    // 有3個元素的切片, len和cap都為3
    d = c[:2]             // 有2個元素的切片, len為2, cap為3
    e = c[0:2:cap(c)]     // 有2個元素的切片, len為2, cap為3
    f = c[:0]             // 有0個元素的切片, len為0, cap為3
    g = make([]int, 3)    // 有3個元素的切片, len和cap都為3
    h = make([]int, 2, 3) // 有2個元素的切片, len為2, cap為3
    i = make([]int, 0, 3) // 有0個元素的切片, len為0, cap為3
)

 

遍歷

    for i := range a {
        fmt.Printf("a[%d]: %d\n", i, a[i])
    }
    for i, v := range b {
        fmt.Printf("b[%d]: %d\n", i, v)
    }
    for i := 0; i < len(c); i++ {
        fmt.Printf("c[%d]: %d\n", i, c[i])
    }

 

添加元素

1.開頭添加(一般都會重新分配內存)

var a = []int{1,2,3}
a = append([]int{0}, a...)        // 在開頭添加1個元素
a = append([]int{-3,-2,-1}, a...) // 在開頭添加1個切片

 

2.末尾添加(注意:容量不足,append會重新分配內存)

var a []int
a = append(a, 1)               // 追加1個元素
a = append(a, 1, 2, 3)         // 追加多個元素, 手寫解包方式
a = append(a, []int{1,2,3}...) // 追加一個切片, 切片需要解包

 

3.中間添加(append和copy組合實現)

// append實現,第二個append調用會創建一個臨時的切片
var a []int
a = append(a[:i], append([]int{x}, a[i:]...)...)     // 在第i個位置插入x
a = append(a[:i], append([]int{1,2,3}, a[i:]...)...) // 在第i個位置插入切片

// append和copy組合實現,避免創建中間的臨時切片
a = append(a, 0) // 先擴容
copy(a[i+1:], a[i:]) // a[i:]向后移動1個位置
a[i] = x             // 設置新添加的元素

// append和copy組合,在指定位置插入切片(多個元素)
a = append(a, x...) // 沒有專門的函數來擴容,只有使用append
copy(a[i+len(x):], a[i:])
copy(a[i:], x)

 

刪除元素

1.刪除元素

a := []int{1, 2, 3}

// 移動數據指針
a = a[1:] // 刪除開頭1個元素
a = a[N:] // 刪除開頭N個元素

// 可以用append原地完成(所謂原地完成是指在原有的切片數據對應的內存區間內完成,不會導致內存空間結構的變化)
a = append(a[:0], a[1:]...) // 刪除開頭1個元素
a = append(a[:0], a[N:]...) // 刪除開頭N個元素

// 用copy完成刪除開頭的元素
a = a[:copy(a, a[1:])] // 刪除開頭1個元素
a = a[:copy(a, a[N:])] // 刪除開頭N個元素

 

2.刪除尾部(最快)

a = a[:len(a)-1]   // 刪除尾部1個元素
a = a[:len(a)-N]   // 刪除尾部N個元素

 

3.刪除中間部分

// 使用append
a = append(a[:i], a[i+1:]...) // 刪除中間1個元素
a = append(a[:i], a[i+N:]...) // 刪除中間N個元素

// 使用copy
a = a[:i+copy(a[i:], a[i+1:])]  // 刪除中間1個元素
a = a[:i+copy(a[i:], a[i+N:])]  // 刪除中間N個元素

 

總結

切片高效操作的要點是要降低內存分配的次數,盡量保證append操作不會超出cap的容量,降低觸發內存分配的次數和每次分配內存大小。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM