golang 切片詳解

2022-10-09 01:03:07 字數 1752 閱讀 3843

1. 切片的定義

切片的結構定義在 reflect.sliceheader

type sliceheader struct

看看切片的幾種定義方式:

var (

a int //nil切片,和nil相等,一般用來表示乙個不存在的切片

b = int{} //空切片,和nil不相等,一般用來表示乙個空的集合

c = int // 有3個元素的切片,len=3,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=3,cap=3

h = make(int, 2, 3) // 有2個元素的切片,len=2,cap=3

i = make(int, 0, 3) // 有0個元素的切片,len=0,cap=3

)

2. 切片的記憶體

下面的trimspace()函式用於刪除byte中的空格。函式的實現利用了長度為0的切片的特性,實現簡單而高效:

func trimspace(s byte) byte

}return b

}

其實類似的根據過濾條件原地修改切片元素的演算法都可以採用類似的處理方式,因為是刪除操作,所以不會出現記憶體不足的情況。

func filter(s byte, fn func(x byte) bool) byte

}return b

}

切片操作不會複製底層的陣列,底層陣列會被儲存在記憶體中,直到它不再被引用。但是有時候可能會因為乙個小的記憶體引用而導致整個底層陣列屬於被使用的狀態,這時會延遲垃圾**對底層陣列的**。

例如下面這一段**,findphonenumber()函式載入整個檔案到記憶體中,然後搜尋第乙個出現的**號碼,最後結果以切片方式返回:

func findphonenumber(filename string) byte

這段**返回的byte指向儲存整個檔案的陣列。由於切片引用了整個原始陣列,導致垃圾**不能及時釋放底層陣列的空間,乙個小小的需求就可能系統需要長時間保留整個檔案資料。

要解決這個問題,通常需要將需要的資料複製到乙個新的切片中,雖然值傳遞有一定的代價,但是切斷了對原始陣列的依賴

func findphonenumber(filename string) byte

, b...)

}

類似的問題可能在刪除切片元素時會遇到。假設切片裡存放的是指標物件,那麼刪除末尾元素後,被刪除的元素依然會被切片底層陣列引用,導致不能夠被及時**。

保險的方式是先講指向需要提前**記憶體的指標設定為nil,保證垃圾**器可以發現需要**的物件,再進行切片的刪除:

var a *int

a[len(a)-1] =nil

a = a[:len(a)-1]

但當容量不足時,可以看到只有在當前元素 i0 小於1024時,才是按2倍速度正常,否則其實每次只增長25%。

其次,在擴容時,應該是按照2^n做一次記憶體向上取整的。

關於golang中的切片詳解

之前對切片的理解是本身是乙個指標,指標指向陣列,因為陣列是值賦值,所以陣列作為函式引數傳遞時,會被複製乙份,傳遞較大陣列時會比較浪費記憶體。之前的理解部分對,但是瑕疵和錯誤的地方太多。切片本身是乙個結構體,它是被golang封裝過的結構體,所以使用起來和陣列差不多,其結構體內容如下 type sli...

golang 切片擷取引數方法詳解

以 s int為例 0.建議 做slice擷取時建議用兩個引數,尤其是從底層陣列進行切片操作時,因為這樣在進行第一次append操作時,會給切片重新分配空間,這樣減少切片對陣列的影響。1.結論 s s low high max 切片的三個引數的切片擷取的意義為 low為擷取的起始下標 含 high為...

golang陣列,切片

陣列 同一種資料型別的固定長度序列 陣列的定義 var a len int 比如 var a 5 int 長度是陣列型別的一部分,因此,var a 5 int 和 var a 10 int 是不同的型別 陣列的初始化 func chushi var age1 5 int var age2 int v...