非懂不可的Slice(二)-- 就要學習 Go 語言

這一節,咱們來討論更多關於Slice的用法。golang

nil切片與空切片

nil切片
var s []int
fmt.Println(s == nil)   // 輸出 true
fmt.Println(len(s),cap(s))   // 輸出:0 0
複製代碼

上面這段代碼聲明瞭一個nil切片s,其實,切片的零值就是nil。爲何?經過上一節咱們知道,由於切片就是一個數組的引用。切片的類型在初始化時已經確認,就是[]Type,上面的代碼就聲明瞭[]int類型的nil切片snil切片的指向底層數組的指針爲nil數組

空切片

如何聲明空切片?有兩種方式:架構

// 一、使用 make 建立空的整型切片
s := make([]int, 0)

// 二、使用切片字面量建立空的整型切片
s := []int{}
fmt.Println(s)   // 輸出:[]
fmt.Println(len(s),cap(s))   // 輸出:0 0
複製代碼

經過上面代碼能夠得出,與nil切片同樣,空切片的長度和容量也都是0,說明切片底層的數組大小爲0,是一個空數組(沒有分配任何的存儲空間)。app

無論是使用 nil 切片仍是空切片,對其調用內置函數appendlencap的效果都是同樣的。函數

copy函數

Go提供了內置函數copy,能夠講一個切片複製到另外一個切片。函數原型:post

func copy(dst, src []Type) int 複製代碼

dst是目標切片,src是源切片,函數返回二者長度的最小值。學習

var s1 []int
s2 := []int{1, 2, 3}
s3 := []int{4, 5, 6, 7}
s4 := []int{1, 2, 3}
// 一、
n1 := copy(s1, s2)
fmt.Printf("n1=%d, s1=%v, s2=%v\n", n1, s1, s2)
fmt.Println("s1 == nil", s1 == nil)
// 二、
n2 := copy(s2, s3)
fmt.Printf("n2=%d, s2=%v, s3=%v\n", n2, s2, s3)
// 三、
n3 := copy(s3, s4)
fmt.Printf("n3=%d, s3=%v, s4=%v\n", n3, s3, s4)
複製代碼

輸出ui

n1=0, s1=[], s2=[1 2 3]
s1 == nil true
n2=3, s2=[4 5 6], s3=[4 5 6 7]
n3=3, s3=[1 2 3 7], s4=[1 2 3]
複製代碼

上面代碼生聲明瞭nil切片s1和三個非空切片s2s3s4。從第一塊代碼塊能夠看到,由於s1nil切片,執行完copy操做以後,s1依然仍是nil。這有別於append函數:spa

var s1 []int
s2 := []int{1, 2, 3}
s1 = append(s1, s2...)
fmt.Println(s1)   // 輸出:[1 2 3]
複製代碼

第二段代碼:因爲s2的長度是3,s3的長度是4,因此執行copy操做只會從s3複製3個元素至s2copy只會複製,不會追加。 第三段代碼也是一樣的道理。.net

函數間傳遞切片

切片在函數間以值的方式傳遞。因爲切片的尺寸很小(在 64 位架構的機器上,一個切片須要 24 字節的內存:指針字段、長度和容量字段各須要 8 字節),在函數間複製和傳遞切片成本也很低。切片發生複製時,底層數組不會被複制,數組大小也不會有影響。

func main() {
	s := []int{0, 1, 2, 3, 4, 5}
	fmt.Printf("%p\n", &s)
	modify(s)
	fmt.Println(s)
}

func modify(s []int) {
	fmt.Printf("%p\n", &s)
	s[1] = 10
}
複製代碼

輸出

0xc000086020
0xc000086040
[0 10 2 3 4 5]
複製代碼

咱們能夠看到,原切片地址和傳遞以後的切片的地址是不同的,說明發生了複製;在函數modify中修改了切片一個值,原切片的值也隨之改變了,說明這兩個切片是共享底層數組的。 在函數間傳遞切片很是高效,並且不須要傳遞指針和處理複雜的語法,只須要複製切片,按本身的業務修改數據,最後傳遞迴一個新的切片副本便可,這也是爲何函數間使用切片傳參,而不是數組傳參的緣由。

刪除切片中的元素

Go沒有提供刪除切片元素的函數,然而,咱們可使用一些「黑科技」達到這樣的目的。

s := []int{1, 2, 3, 4, 5, 6}
s = append(s[:2], s[3:]...)    // 刪除索引爲2的元素
fmt.Println(s)
複製代碼

輸出:

[1 2 4 5 6]
複製代碼

經過這兩節詳解,相信你已經掌握了Slice,建議你們要多多練習!


(全文完)

原創文章,若需轉載請註明出處!
歡迎掃碼關注公衆號「Golang來啦」或者移步 seekload.net ,查看更多精彩文章。

公衆號「Golang來啦」給你準備了一份神祕學習大禮包,後臺回覆【電子書】領取!

公衆號二維碼
相關文章
相關標籤/搜索