golang 定義乙個空切片 go語言切片用法詳解

2021-10-13 07:52:07 字數 4147 閱讀 8915

1. 定義

切片在go語言的原始碼定義如下所示,由於其資料結構中有指向底層陣列的指標,所以切片是一種引用型別。

// src/runtime/slice.go

type slice struct

s1 := array[0:4]

s2 := array[:4]

s3 := array[2:]

fmt.println(s1) // [0 1 2 3]

fmt.println(s2) // [0 1 2 3]

fmt.println(s3) // [2 3 4 5 6]

(2) 通過內建函式make建立切片

切片使用之前需要make是因為make操作要完成切片底層陣列的建立及初始化,由make建立的切片個元素被預設初始化位切片元素型別的預設值。例如:

// len = 10, cap = 10

a := make(int, 10)

// len = 10, cqp = 15

b := make(int, 10, 15)

fmt.println(a) // 結果為 [0 0 0 0 0 0 0 0 0 0]

fmt.println(b) // 結果為 [0 0 0 0 0 0 0 0 0 0]

// 直接宣告切片型別變數是沒有意義的(使用前必須make)

var c int

fmt.println(c) // 結果為

(3) 通過切片字面量來建立切片

// 建立長度和容量都是5個元素的字串切片

s1 := string

// 注意和字串陣列區別(和[...]), 下面是宣告陣列

arr := [...]string

// 建立長度和容量都是3個元素的整形切片

s2 := int

(4) 使用索引建立切片(比較少用)

// 建立字串切片

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

s3 := string

(5) 建立空切片

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

s1 := make(int, 0)

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

s2 := int{}

空切片底層陣列包含0個元素,也沒有分配任何儲存空間。不管使用nil切片(沒有make的切片)還是空切片,對其呼叫內建函式的效果都是一樣的。

4. 切片支援的操作

內建函式len()返回切片長度

內建函式cap()返回切片底層陣列容量

內建函式copy()用於複製乙個切片

示例如下:

a := [...]int

b := make(int, 2, 4)

c := a[0:3]

fmt.println(len(b)) // 結果為 2

fmt.println(cap(b)) // 結果為 4

// 切片b中新增元素

fmt.println(b) // 結果為 [0 0 1]

fmt.println(len(b)) // 結果為 3

// 切片b中新增切片

fmt.println(b) // 結果為 [0 0 1 0 1 2]

fmt.println(len(b)) // 結果為 6

fmt.println(cap(b)) // 結果為 8 底層陣列發生拓展

d := make(int, 2, 2)

copy(d, c) // copy只會複製c和d中長度最小的

fmt.println(d) // 結果為 [0 1]

fmt.println(len(d)) // 結果為 2

fmt.println(cap(d)) // 結果為 2

5. 切片的使用

(1) 賦值

對切片中的某個元素賦值和陣列中元素賦值的方法完全一樣。用操作符就可以改變某個元素的值,**如下:

// 建立乙個整形切片

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

s := int

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

s[1] = 200

(2) 對切片進行切片

切片之所以稱為切片,是因為建立乙個切片就是把底層陣列切出一部分,**如下:

// 建立乙個整形切片

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

slice := int

// 建立乙個新切片

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

newslice := slice[1:3]

fmt.println(newslice) // 結果為 [20 30]

對切片進行切片後,其記憶體中的分布如下圖所示:

計算切片的長度和容量:

對底層陣列容量是k的切片slice[i:j]來說

切片長度:j - i, 切片容量:k - i

例如,對於圖2中的切片newslice, 長度為3 - 1 = 2, 容量為5 - 1 = 4。

(3) 修改切片內容

// 建立乙個整形切片

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

slice := int

// 建立乙個新切片

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

newslice := slice[1:3]

// 修改newslice索引為1的元素,同時也修改了原來的slice索引為2的元素

newslice[1] = 32

fmt.println(newslice) // 結果為 [20 32]

fmt.println(slice) // [10 20 32 40 50]

切片只能訪問到其長度內的元素。試圖訪問超出其長度的元素將會導致語言執行時異常。

(4) 切片增長

// 建立乙個整形切片

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

slice := int

// 建立乙個新切片

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

newslice := slice[1:3]

fmt.println(newslice) // 結果為 [20 30]

fmt.println(slice) // [10 20 30 40 50]

fmt.println(newslice) // 結果為 [20 30 300 400] (發生變化)

fmt.println(slice) // [10 20 30 300 400] (原來的位置上的元素被覆蓋)

我們再來看另外一種特殊的情況,**如下。

// 建立乙個整形切片

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

slice := int

// 建立乙個新切片

// 其長度為4個元素!!!容量為4個元素

newslice := slice[1:5]

fmt.println(newslice) // 結果為 [20 30 40 50]

fmt.println(slice) // [10 20 30 40 50]

fmt.println(newslice) // 結果為 [20 30 40 50 300 400] (發生變化)

fmt.println(cap(newslice)) // 結果為8,表明newslice底層陣列的容量拓展為原來的2倍

fmt.println(slice) // [10 20 30 40 50] (沒有發生變化!!!)

(5) 切片使用的乙個重要細節

(6) 在函式間傳遞切片

在64位架構的機器上,乙個切片需要24位元組的記憶體(3個字段)。由於切片關聯的資料都包含在底層陣列裡,不屬於切片本身,所以將切片複製到任意函式的時時候,只複製切片本身,不會涉及底層陣列。

在函式間傳遞24位元組的資料會非常簡單快速。這也是切片效率高的地方。不需要傳遞指標和複雜的語法,只需要複製切片,按想要的方式修改資料,然後返回乙份新的切片副本。示例**如下。

package main

// 函式foo接收乙個整形切片,並返回這個切片

func foo(slice int) int {

return slice

func main() {

// 分配100萬個整形值的切片

slice := make(int, 1e6)

// 將slice傳遞到函式foo

slice = foo(slice)

切片用法的演示就到這裡了~~~

我是lioney,年輕的後端攻城獅一枚,愛鑽研,愛技術,愛分享。

golang 兩個go程輪流列印乙個切片

使用兩個 channel,用來傳值 李培冠部落格 兩個 go 程輪流列印乙個切片。package main import fmt sync 兩個 go 程輪流列印乙個切片 func main var i int var wg sync.waitgroup wg.add 2 gofunc wg.don...

定義乙個空切片 第五章(第1節) 切片

比如我們取乙個有序集合 list 型別的變數 l 的前 2 個元素做為乙個集合,可以用 l 0 l 1 這種方法,如果要取前 n 個元素,但是 n 很大,我們就需要乙個個列出來或者用迴圈操作等,這樣就會可讀性差或者操作麻煩等等。python 提供了取有序集合 str,list,tuple 或支援通過...

golang定義空指標 Go語言指標宣告及操作方法

指標 pointer 是程式語言中的乙個物件,利用位址,它的值直接指向 points to 存在電腦儲存器中另乙個地方的值。由於通過位址能找到所需的變數單元,可以說,位址指向該變數單元。因此,將位址形象化的稱為 指標 意思是通過它能找到以它為位址的記憶體單元。乙個指標變數指向了乙個值的記憶體位址。g...