目錄
- Slice(切片)
- 基于數組生成切片
- 切片修改
- 切片聲明
- Append
- 切片元素循環
Slice(切片)
切片和數組類似,可以把它理解為動態數組。切片是基于數組實現的,它的底層就是一個數組。對數組任意分隔,就可以得到一個切片。現在我們通過一個例子來更好地理解它,同樣還是基于前面的 array。
基于數組生成切片
下面代碼中的 array[2:5] 就是獲取一個切片的操作,它包含從數組 array 的索引 2 開始到索引 5 結束的元素:
array:=[5]string{"a","b","c","d","e"}
slice:=array[2:5]
fmt.Println(slice)
注意:這里是包含索引 2,但是不包含索引 5 的元素,即在 : 右邊的數字不會被包含。
//基于數組生成切片,包含索引start,但是不包含索引end
slice:=array[start:end]
所以 array[2:5] 獲取到的是 c、d、e 這三個元素,然后這三個元素作為一個切片賦值給變量 slice。
切片和數組一樣,也可以通過索引定位元素。這里以新獲取的 slice 切片為例,slice[0] 的值為 c,slice[1] 的值為 d。
有沒有發現,在數組 array 中,元素 c 的索引其實是 2,但是對數組切片后,在新生成的切片 slice 中,它的索引是 0,這就是切片。雖然切片底層用的也是 array 數組,但是經過切片后,切片的索引范圍改變了。
通過下圖可以看出,切片是一個具備三個字段的數據結構,分別是指向數組的指針 data,長度 len 和容量 cap:

這里有一些小技巧,切片表達式 array[start:end] 中的 start 和 end 索引都是可以省略的,如果省略 start,那么 start 的值默認為 0,如果省略 end,那么 end 的默認值為數組的長度。如下面的示例:
- array[:4] 等價于 array[0:4]。
- array[1:] 等價于 array[1:5]。
- array[:] 等價于 array[0:5]。
切片修改
切片的值也可以被修改,這里也同時可以證明切片的底層是數組。
對切片相應的索引元素賦值就是修改,在下面的代碼中,把切片 slice 索引 1 的值修改為 f,然后打印輸出數組 array:
slice:=array[2:5]
slice[1] ="f"
fmt.Println(array)
可以看到如下結果:
[a b c f e]
數組對應的值已經被修改為 f,所以這也證明了基于數組的切片,使用的底層數組還是原來的數組,一旦修改切片的元素值,那么底層數組對應的值也會被修改。
切片聲明
除了可以從一個數組得到切片外,還可以聲明切片,比較簡單的是使用 make 函數。
下面的代碼是聲明了一個元素類型為 string 的切片,長度是 4,make 函數還可以傳入一個容量參數:
在下面的例子中,指定了新創建的切片 []string 容量為 8:
slice1:=make([]string,4,8)
這里需要注意的是,切片的容量不能比切片的長度小。
切片的長度你已經知道了,就是切片內元素的個數。那么容量是什么呢?其實就是切片的空間。
上面的示例說明,Go 語言在內存上劃分了一塊容量為 8 的內容空間(容量為 8),但是只有 4 個內存空間才有元素(長度為 4),其他的內存空間處于空閑狀態,當通過 append 函數往切片中追加元素的時候,會追加到空閑的內存上,當切片的長度要超過容量的時候,會進行擴容。
切片不僅可以通過 make 函數聲明,也可以通過字面量的方式聲明和初始化,如下所示:
slice1:=[]string{"a","b","c","d","e"}
fmt.Println(len(slice1),cap(slice1))
可以注意到,切片和數組的字面量初始化方式,差別就是中括號 [] 里的長度。此外,通過字面量初始化的切片,長度和容量相同。
Append
我們可以通過內置的 append 函數對一個切片追加元素,返回新切片,如下面的代碼所示:
//追加一個元素
slice2:=append(slice1,"f")
//多加多個元素
slice2:=append(slice1,"f","g")
//追加另一個切片
slice2:=append(slice1,slice...)
append 函數可以有以上三種操作,你可以根據自己的實際需求進行選擇,append 會自動處理切片容量不足需要擴容的問題。
小技巧:在創建新切片的時候,最好要讓新切片的長度和容量一樣,這樣在追加操作的時候就會生成新的底層數組,從而和原有數組分離,就不會因為共用底層數組導致修改內容的時候影響多個切片。
切片元素循環
切片的循環和數組一模一樣,常用的也是 for range 方式,這里就不再進行舉例,當作練習題留給你。
在 Go 語言開發中,切片是使用最多的,尤其是作為函數的參數時,相比數組,通常會優先選擇切片,因為它高效,內存占用小。
到此這篇關于Go之集合slice的實現的文章就介紹到這了,更多相關Go 集合slice內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- 使用go操作redis的有序集合(zset)
- MongoDB基礎入門之創建、刪除集合操作
- Go語言之自定義集合Set
- MongoDB在不同主機間復制數據庫和集合的教程
- 詳解MongoDB中創建集合與刪除集合的操作方法