golang中數(shù)組與切片的區(qū)別詳析
一. Go 切片和 Go 數(shù)組定義
Go 切片:又稱動態(tài)數(shù)組,它實際是基于數(shù)組類型做的一層封裝。
Go 數(shù)組:數(shù)組是內(nèi)置(build-in)類型,是一組同類型數(shù)據(jù)的集合,它是值類型,通過從 0 開始的下標(biāo)索引訪問元素值。在初始化后長度是固定的,無法修改其長度。當(dāng)作為方法的參數(shù)傳入時將復(fù)制一份數(shù)組而不是引用同一指針。數(shù)組的長度也是其類型的一部分,通過內(nèi)置函數(shù) len(array)獲取其長度。
二.切片與數(shù)組的區(qū)別
Go 數(shù)組與像 C/C++等語言中數(shù)組略有不同:
1. Go 中的數(shù)組是值類型,換句話說,如果你將一個數(shù)組賦值給另外一個數(shù)組,那么,實際上就是將整個數(shù)組拷貝一份。因此,在 Go 中如果將數(shù)組作為函數(shù)的參數(shù)傳遞的話,那效率就肯定沒有傳遞指針高了。
2. 數(shù)組的長度也是類型的一部分,這就說明[10]int和[20]int不是同一種數(shù)據(jù)類型。并且Go 語言中數(shù)組的長度是固定的,且不同長度的數(shù)組是不同類型,這樣的限制帶來不少局限性。
3. 而切片則不同,切片(slice)是一個擁有相同類型元素的可變長序列,可以方便地進行擴容和傳遞,實際使用時比數(shù)組更加靈活,這也正是切片存在的意義。而且切片是引用類型,因此在當(dāng)傳遞切片時將引用同一指針,修改值將會影響其他的對象。
三. 切片使用
切片定義方式
var a []int //nil切片,和nil相等,一般用來表示一個不存在的切片
var b []int{} //空切片,和nil不相等,一般用來表示一個空的集合
var c []int{1, 2, 3} //有3個元素的切片,len和cap都為3
var d = c[:2] //有2個元素的切片,len為2,cap為3
var e = c[:2:cap(c)] //有2個元素的切片,len為2,cap為3
var f = c[:0] //有0個元素的切片,len為0,cap為3
var g = make([]int, 3) //創(chuàng)建一個切片,len和cap均為3
var h = make([]int, 3, 6) //創(chuàng)建一個切片,len為3,cap為5
var i = make([]int, 0, 3) //創(chuàng)建一個切片,len為0,cap為3
從數(shù)組中切取切片
數(shù)組和切片是緊密相連的。切片可以用來訪問數(shù)組的部分或全部元素,而這個數(shù)組稱為切片的底層數(shù)組。切片的指針指向數(shù)組第一個可以從切片中訪問的元素,這個元素并不一定是數(shù)組的第一個元素。
一個底層數(shù)組可以對應(yīng)多個切片,這些切片可以引用數(shù)組的任何位置,彼此之前的元素可以重疊。
slice 操作符 s[i:j] 創(chuàng)建了一個新的 slice,這個新的 slice 引用了 s 中從 i 到 j-1 索引位置的所有元素。
如果表達式省略了 i,那么默認是s[0:j];如果省略了 j,默認是s[i:len(s)];
//創(chuàng)建一個數(shù)組
months := [...]string{1:"January", /*...*/, 12: "December"}
Q2 := months[4:7]
summer := months[6:9]
fmt.Println(Q2) //["April" "May" "June"]
fmt.Println(summer) //["June" "July" "August"]
月份名稱字符串?dāng)?shù)組與其對應(yīng)的兩個元素重疊的 slice 圖示

注意:切片與原數(shù)組或切片共享底層空間,修改切片會影響原數(shù)組或切片
迭代切片
切片可以用 range 迭代,但是要注意:如果只用一個值接收 range,則得到的只是切片的下標(biāo),用兩個值接收 range,則得到的才是下標(biāo)和對應(yīng)的值。
//使用一個值接收range, 則得到的是切片的下標(biāo)
for i := range months {
fmt.Println(i) //返回下標(biāo) 0 1 ... 12
}
//使用兩個值接收range,則得到的是下標(biāo)和對應(yīng)的值
for i, v := range months {
fmt.Println(i, v) //返回下標(biāo)0 1 ... 12 和 值 "" "January" ... "December"
}
切片拷貝
使用copy內(nèi)置函數(shù)拷貝兩個切片時,會將源切片的數(shù)據(jù)逐個拷貝到目的切片指向的數(shù)組中,拷貝數(shù)量取兩個切片的最小值。
例如長度為 10 的切片拷貝到長度為 5 的切片時,將拷貝 5 個元素。也就是說,拷貝過程中不會發(fā)生擴容。
copy 函數(shù)有返回值,它返回實際上復(fù)制的元素個數(shù),這個值就是兩個 slice 長度的較小值。
切片擴容-append 函數(shù)
//通過append()函數(shù)可以在切片的尾部追加 N 個元素
var a []int
a = append(a, 1) // 追加一個元素
a = append(a, 1, 2, 3) // 追加多個元素
a = append(a, []int{1, 2, 3}...) // 追加一個切片,注意追加切片時后面要加...
//使用 append()函數(shù)也可以在切片頭部添加元素
a = append([]int{0}, a...) // 在開頭添加一個元素
a = append([]int{1, 2, 3}, a...) // 在開頭添加一個切片
注:從頭部添加元素會引起內(nèi)存的重分配,導(dǎo)致已有元素全部復(fù)制一次。因此從頭部添加元素的開銷要比從尾部添加元素大很多
//通過 append()函數(shù)鏈?zhǔn)讲僮鲝闹虚g插入元素
a = append(a[:i], append([]int{x}, a[i:]...)...) //在第i個位置上插入x
a = append(a[:i], append([]int{1, 2, 3}, a[i:]...)...) //在第i個位置上插入切片
使用鏈?zhǔn)讲僮髟诓迦朐兀趦?nèi)層 append 函數(shù)中會創(chuàng)建一個臨式切片,然后將a[i:]內(nèi)容復(fù)制到新創(chuàng)建的臨式切片中,再將臨式切片追加至a[:i]中。
通過 append()和 copy()函數(shù)組合從中間插入元素
使用這種方式可以避免創(chuàng)建過程中間的臨式切片,也可以做到從中間插入元素
//中間插入一個元素 a = append(a, 0) //切片擴展一個空間 copy(a[i+1:], a[i:]) //a[i:]向后移動一個位置 a[i] = x //設(shè)置新添加的元素 //中間插入多個元素 a = append(a, x...) //為x切片擴展足夠的空間 copy(a[i+len(x):], a[i:]) //a[i:]向后移動len(x)個位置 copy(a[i:], x) //復(fù)制新添加的切片
使用此方式雖然稍顯復(fù)雜,但是可以減少創(chuàng)建中間臨時切片的開銷。
刪除元素
很遺憾,Go 語言中并沒有提供直接刪除指定位置元素的方式。不過根據(jù)切片的性質(zhì),我們可以通過巧妙的拼接切片來達到刪除指定數(shù)據(jù)的目的。
a = []int{1, 2, 3}
//刪除尾部元素
a = a[:len(a) - 1] //刪除尾部一個元素
a = a[:len(a) - N] //刪除尾部N個元素
//刪除頭部元素
a = [1:] //刪除開頭1個元素
a = [N:] //刪除開頭N個元素
//刪除中間元素
a = append(a[:i], a[i+1:]...) //刪除中間一個元素
a = append(a[:i], a[i+N:]...) //刪除中間N個元素
總結(jié)
到此這篇關(guān)于golang中數(shù)組與切片區(qū)別的文章就介紹到這了,更多相關(guān)go數(shù)組與切片區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言基礎(chǔ)學(xué)習(xí)之?dāng)?shù)組的使用詳解
數(shù)組相必大家都很熟悉,各大語言也都有數(shù)組的身影。Go 語言也提供了數(shù)組類型的數(shù)據(jù)結(jié)構(gòu)。本文就來通過一些簡單的示例帶大家了解一下Go語言中數(shù)組的使用,希望對大家有所幫助2022-12-12
7分鐘讀懂Go的臨時對象池pool以及其應(yīng)用場景
這篇文章主要給大家介紹了關(guān)于如何通過7分鐘讀懂Go的臨時對象池pool以及其應(yīng)用場景的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或使用Go具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧2018-11-11
CSP communicating sequential processes并發(fā)模型
這篇文章主要為大家介紹了CSP communicating sequential processes并發(fā)模型,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05
基于Golang實現(xiàn)Redis分布式鎖解決秒殺問題
這篇文章主要給大家介紹了使用Golang實現(xiàn)Redis分布式鎖解決秒殺問題,文中有詳細的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下2023-08-08

