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...