Golang切片學習筆記

2021-10-12 00:01:01 字數 4763 閱讀 8163

在 golang 中可以通過多種方式建立和初始化切片。是否提前知道切片所需的容量通常會決定如何建立切片

1.1 通過 make() 函式建立切片

使用 golang 內建的 make() 函式建立切片,此時需要傳入乙個引數來指定切片的長度:

// 建立乙個整型切片

// 其長度和容量都是 5 個元素

slice := make(int, 5)

分別指定長度和容量時,建立的切片,底層陣列的長度是指定的容量,但是初始化後並不能

訪問所有的陣列元素。

注意,golang 不允許建立容量小於長度的切片,當建立的切片容量小於長度時會在編譯時刻報錯:

// 建立乙個整型切片

// 使其長度大於容量

mynum := make(int, 5, 3)

1.2 通過字面量建立切片另一種常用的建立切片的方法是使用切片字面量,這種方法和建立陣列類似,只是不需要指定[ ]運算子裡的值。初始的長度和容量會基於初始化時提供的元素的個數確定:

// 建立字串切片

// 其長度和容量都是 3 個元素

mystr := string

// 建立乙個整型切片

// 其長度和容量都是 4 個元素

mynum := int

當使用切片字面量建立切片時,還可以設定初始長度和容量。要做的就是在初始化時給出所需的長度和容量作為索引。下面的語法展示了如何使用索引方式建立長度和容量都是100個元素的切片:

// 建立字串切片

// 使用空字串初始化第 100 個元素

mystr := string

1.3 區分陣列的宣告和切片的宣告方式當使用字面量來宣告切片時,其語法與使用字面量宣告陣列非常相似。二者的區別是:如果在 運算子裡指定了乙個值,那麼建立的就是陣列而不是切片。只有在 中不指定值的時候,建立的才是切片。看下面的例子:

// 建立有 3 個元素的整型陣列

myarray := [3]int

// 建立長度和容量都是 3 的整型切片

myslice := int

有時,程式可能需要宣告乙個值為 nil 的切片(也稱nil切片)。只要在宣告時不做任何初始化,就會建立乙個 nil 切片

// 建立 nil 整型切片

var mynum int

在 golang 中,nil 切片是很常見的建立切片的方法。nil 切片可以用於很多標準庫和內建函式。在需要描述乙個不存在的切片時,nil 切片會很好用。比如,函式要求返回乙個切片但是發生異常的時候。下圖描述了 nil 切片的狀態:

空切片和 nil 切片稍有不同,下面的**分別通過 make() 函式和字面量的方式建立空切片:

// 使用 make 建立空的整型切片

mynum := make(int, 0)

// 使用切片字面量建立空的整型切片

mynum := int{}

對切片裡某個索引指向的元素賦值和對陣列裡某個索引指向的元素賦值的方法完全一樣。使

用 操作符就可以改變某個元素的值,下面是使用切片字面量來宣告切片:

// 建立乙個整型切片

// 其容量和長度都是 5 個元素

mynum := int

// 改變索引為 1 的元素的值

mynum [1] = 25

切片之所以被稱為切片,是因為建立乙個新的切片,也就是把底層陣列切出一部分。通過切片建立新切片的語法如下:

slice[i:j]

slice[i:j:k]

其中 i 表示從 slice 的第幾個元素開始切,j 控制切片的長度(j-i),k 控制切片的容量(k-i),如果沒有給定 k,則表示切到底層陣列的最尾部。下面是幾種常見的簡寫形式:

slice[i:]  // 從 i 切到最尾部

slice[:j] // 從最開頭切到 j(不包含 j)

slice[:] // 從頭切到尾,等價於複製整個 slice

讓我們通過下面的例子來理解通過切片建立新的切片的本質:

// 建立乙個整型切片

// 其長度和容量都是 5 個元素

mynum := int

// 建立乙個新切片

// 其長度為 2 個元素,容量為 4 個元素

newnum := slice[1:3]

執行上面的**後,我們有了兩個切片,它們共享同一段底層陣列,但通過不同的切片會看到底層陣列的不同部分:

注意,擷取新切片時的原則是 "左含右不含"。所以 newnum 是從 mynum 的 index=1 處開始擷取,擷取到 index=3 的前乙個元素,也就是不包含 index=3 這個元素。所以,新的 newnum 是由 mynum 中的第2個元素、第3個元素組成的新的切片構,長度為 2,容量為 4。切片 mynum 能夠看到底層陣列全部 5 個元素的容量,而 newnum 能看到的底層陣列的容量只有 4 個元素。newnum 無法訪問到底層陣列的第乙個元素。所以,對 newnum 來說,那個元素就是不存在的。

共享底層陣列的切片

// 修改 newnum 索引為 1 的元素

// 同時也修改了原切片 mynum 的索引為 2 的元素

newnum[1] = 35

把 35 賦值給 newnum 索引為 1 的元素的同時也是在修改 mynum 索引為 2 的元素:

切片只能訪問到其長度內的元素

切片只能訪問到其長度內的元素,試圖訪問超出其長度的元素將會導致語言執行時異常。在使用這部分元素前,必須將其合併到切片的長度裡。

mynum := int

// 建立新的切片,其長度為 2 個元素,容量為 4 個元素

newnum := mynum[1:3]

// 使用原有的容量來分配乙個新元素

// 將新元素賦值為 60

執行上面的**後的底層資料結構如下圖所示:

// 建立乙個長度和容量都是 4 的整型切片

mynum := int

// 向切片追加乙個新元素

// 將新元素賦值為 50

擴容**示例:

mynum := int

slice :=mynum[1:3]

fmt.println(slice)

fmt.println(mynum)

fmt.println(slice)

fmt.println(mynum)

fmt.println(slice)

fmt.println(mynum)

fmt.println(slice)

fmt.println(mynum)

mynum[1]=50

fmt.println("new",slice)

fmt.println(mynum)

輸出結果(手動加回車隔開了結果):

[20 30]

[10 20 30 40 50]

[20 30 777]

[10 20 30 777 50]

[20 30 777 888]

[10 20 30 777 888]

[20 30 777 888 999]

[10 20 30 777 888]

new [20 30 777 888 999]

[10 50 30 777 888]

// 建立乙個長度和容量都是 4 的整型切片

mynum := int

// 向切片追加乙個新元素

// 將新元素賦值為 50

golang 內建的 copy() 函式可以將乙個切片中的元素拷貝到另乙個切片中,其函式宣告為:

func copy(dst, src type) int

它表示把切片 src 中的元素拷貝到切片 dst 中,返回值為拷貝成功的元素個數。如果 src 比 dst 長,就截斷;如果 src 比 dst 短,則只拷貝 src 那部分:

num1 := int

num2 := make(int, 5)

count := copy(num2, num1)

fmt.println(count)

fmt.println(num2)

執行這段單面,輸出的結果為:

3

[10 20 30 0 0]

3 表示拷貝成功的元素個數。

三 Golang學習筆記 切片

陣列存在的問題 定義完,長度固定,不易擴充套件 切片 長度不固定,可以追加元素,可以理解成 動態陣列 但不是陣列 func main 3.使用make函式建立 make 型別,長度 初始化空間 容量 初始化和空閒 長度不能大於容量,第三個引數可以省略 s make int,3 5 fmt.print...

golang 切片學習

package main 這裡只說些自己理解的,當然切片的操作遠遠不止這些。import fmt reflect 學習切片首先要明白len和cap的區別。len 是儲存資料多少,cap 是容量大小。舉個例子乙個大會堂可以容納1000人這是cap,但是實際裡面隻座了100人這是len func mai...

golang筆記 Slice切片

sliceslice代表變長的序列,序列中每個元素都有相同的型別。語法和陣列很像,只是沒有固定長度。引用型別 動態陣列 從概念上來說,slice像乙個結構體,這個結構體包含了三個元素 乙個指標,指向陣列中slice指定的開始位置 長度,即slice的長度 最大長度,也就是slice開始位置到陣列的最...