今天,咱們來聊一聊 Golang 中的 Slice(切片)

前言:
由於工做須要,最近接觸 Golang 比較多。
也但願本身的技術棧能從一個 iOS 轉變成 iOS / Golang。
golang


那麼,今天咱們來聊一聊Golang中的數組(Array)和切片(Slice)。數組

1、Array(數組)

數組咱們確定都是熟悉的,
在Go語言中數組(Array)在初始化後,長度是固定的。bash

與其餘語言相似,在這裏舉一些在Go中數組的簡單demo。app

var arr [10]int // 聲明,len與cap爲10,值默認補0。
arr := []int {1,2,3,4} // 快速聲明,len與cap爲4,值爲[1,2,3,4]。
arr := [5]int {1,2,3,4} // 快速聲明,len與cap爲5,值爲[1,2,3,4,0],末尾默認補0。

// 數組的遍歷
for i := 0; i < len(arr); i++ {
	fmt.Println(arr[i])
}
複製代碼

2、Slice(切片)

接下來是今天的主角:Slice。ui

首先,切片是一種引用類型。(與字典map、通道channel同樣,都是引用類型)
有點相似於咱們iOS中的MutableArray
暫時可理解爲一種可變長的「動態數組」。spa

注意:
所以,咱們取數組的切片時,若是不但願切片的修改會對原有數組產生影響的話,須要對Slice進行Copy操做。
code

基本使用

numbers := []int{1,2,3,4,5,6,7,8,9,10}

// 半閉半開結構
slice1 := numbers[:] // 直接對numbers的引用
slice1 = numbers[1:10] // 從numbers[1]到numbers[9]
slice1 = numbers[:5] // 從開始到numbers[4]
slice1 = numbers[7:] // 從numbers[7]開始到末尾

slice1 = append(slice1, 1,2,3,4,5) // 追加長度
fmt.Println(slice1) // 打印:[8 9 10 1 2 3 4 5]

slice2 := make([]int, len(slice1), cap(slice1)*2) // 手動聲明一個slice2,最大長度cap爲slice1的兩倍。
copy(slice2,slice1) //將slice1的數據copy到slice2
slice2 = append(slice2,1,2,3) // 在對slice2進行追加

fmt.Println(slice1)  // 打印:[8 9 10 1 2 3 4 5]
fmt.Println(slice2)  // 打印:[8 9 10 1 2 3 4 5 1 2 3]

fmt.Printf("len = %d, cap = %d", len(slice1), cap(slice1)) // 打印當前長度len,與最大容量cap複製代碼

擴容策略

Slice的長度(len)即將超過最大容量(cap)時,Go語言會對Slice進行擴容。string

具體策略爲:table

  • Slice的長度(len)小於1024時,Go語言會對該Slice進行 「2倍」擴容
  • Slice的長度(len)大於等於1024時,Go語言會對該Slice進行 「1.25倍」擴容
len 擴容策略
<1024 2倍擴容
>=1024 1.25倍擴容

感興趣的同窗,可使用下面的代碼,本身試一下它的擴容策略。class

slice2 := make([]int,10,10)
fmt.Printf("len = %d, cap = %d\n", len(slice2), cap(slice2)) // 打印當前長度len,與最大容量cap。 // 獲取len與cap的長度。
slice2 = append(slice2, 1,2,3,4,5) // 追加數據
fmt.Printf("len = %d, cap = %d\n", len(slice2), cap(slice2)) // 打印當前長度len,與最大容量cap。 // 獲取len與cap的長度。
複製代碼

一些注意點(坑)

  1. 切記切記,切片是一種引用類型。若是改切片的值不但願改動原有數據,必定要先copy一份。

  2. 對切片的遍歷時,系統會對value進行一次值拷貝。所以不能對value進行引用操做,不然可能會形成panic。若是須要引用操做,請去下標。

相關文章
相關標籤/搜索