Golang slice注意啦

日常開發中slice經常用,就是對於一個老司機來說有時也容易忽略。一起看下:

Golang slice注意啦

//Slice 數據結構

type Slice struct {

ptr unsafe.Pointer // Array pointer

len int // slice length

cap int // slice capacity

}

//使用make創建

make([]T, length, capacity)

len()取數組長度,在內存中進行了初始化實際存在的元素的個數

cap()取數組容量,最大可存放元素個數(每次cap改變的時候指向array內存的指針都在變化)

注意:slice的容量,如果通過make函數創建slice的時候指定了容量參數,那內存管理器會根據指定的容量的值先劃分一塊兒內存空間,然後才在其中按長度,存放數組元素,多餘的部分處於空閒狀態。

在slice上追加元素的時候,首先會到這塊兒空閒的內存中,如果添加的元素的個數超過了容量的值,內存管理器會重新劃分一塊容量值為原容量2倍大小的內存空間,這個機制可以提升運算性能,因為內存的頻繁重新劃分會降低性能。

實際go在append的時候放大cap是有規律的。在 cap 小於1024的情況下是每次擴大到 2 * cap ,當大於1024之後就每次擴大到 1.25 * cap 。

在實際使用中,我們最好事先預期好一個cap,這樣在使用append的時候可以避免反覆重新分配內存複製之前的數據,減少不必要的性能消耗。

示例:

package main

import "fmt"

func main() {

/* 創建切片 */

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

printSlice(numbers)

/* 打印原始切片 */

fmt.Println("numbers ==", numbers)

/* 打印子切片從索引1(包含) 到索引4(不包含)*/

fmt.Println("numbers[1:4] ==", numbers[1:4])

/* 默認下限為 0*/

fmt.Println("numbers[:3] ==", numbers[:3])

/* 默認上限為 len(s)*/

fmt.Println("numbers[4:] ==", numbers[4:])

numbers1 := make([]int,0,5)

printSlice(numbers1)

/* 打印子切片從索引 0(包含) 到索引 2(不包含) */

number2 := numbers[:2]

printSlice(number2)

/* 打印子切片從索引 2(包含) 到索引 5(不包含) */

number3 := numbers[4:5]

printSlice(number3)

number3 = append(number3, 4,5,6,7,8)

printSlice(number3)

}

func printSlice(x []int){

fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)

}

執行以上代碼輸出結果為:

len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]

numbers == [0 1 2 3 4 5 6 7 8]

numbers[1:4] == [1 2 3]

numbers[:3] == [0 1 2]

numbers[4:] == [4 5 6 7 8]

len=0 cap=5 slice=[]

len=2 cap=9 slice=[0 1]

len=3 cap=5 slice=[4] //此時指針已經到index 2 處,所以cap容量為9-2=7

len=6 cap=10 slice=[5 6 4 5 6 7 8] //此時cap已經擴容為2倍

更多內容請關注每日編程,每天進步一點。


分享到:


相關文章: