golang 的 array & slice 是個很有趣的東西,接下來就直接進入正題

Array

package main

import (
	"fmt"
)

func main() {
	var a [5]string
	a[0] = "A"
	a[1] = "B"
	a[2] = "C"
	a[3] = "D"
	a[4] = "E"
	fmt.Printf("array %#v\n", a)
}

https://play.golang.org/p/HmHwsNgE5R8

看看 Array 的示意圖

Array

Slice

package main

import (
	"fmt"
)

func main() {
	var a []string
	a = make([]string, 5, 5)
	a[0] = "A"
	a[1] = "B"
	a[2] = "C"
	a[3] = "D"
	a[4] = "E"
	fmt.Printf("array %#v\n", a)
}

// slice 需要使用 make 做初始化才能開始使用

https://play.golang.org/p/LrDLjK8sQfT

這是兩者最明顯的差別,接下來談談 Slice 內部運作的原理

首先 Slice 裡面會有三種資料型態紀錄

Slice

如果以上面 code 範例示意,他的初始化圖會像下面這樣

Slice init

那我們繼續延伸一下

package main

import (
	"fmt"
)

func main() {
	var a []string
	a = make([]string, 5, 5)
	a[0] = "A"
	a[1] = "B"
	a[2] = "C"
	a[3] = "D"
	a[4] = "E"
	fmt.Printf("a array %#v\n", a)

	s := a[2:4]
	//s[0] == "C"
	//s[1] == "D"
	//len(s) == 2
	//cap(s) == 3
	s[0] = "Z"
	// a[2] == "Z" 這段是拿來證明 s是參照到 a
	fmt.Printf("s array %#v\n", s)
	fmt.Printf("a array %#v\n", a)
}

https://play.golang.org/p/MKojisrB5DO

Slice slice

Slice 切片出來的東西,都是創建一個新的Slice指向原本的Slice,所以原本的abcde slice,被切成 2-4,就會變成只有 C 跟 D, 但他的容量(cap)一開始規劃出來是 5,5-2=3,長度(len)則是 4-2=2。

Slice 有一個重點就是在於 長度(len)不可大於(cap)否則會噴錯。

Slice 陷阱

我們常常需要取用某個小段的 Slice ,但 Slice 的原理都是給出參照,以上面為例,我們可能只需要 C, D 兩值,但是用 Slice 取出來卻會造成,其他 A , B , E 都一直存活著, 比較好的作法是用 copy,要如何 copy 呢,來看個範例

copy 是 buit-in function

package main

import (
	"fmt"
)

func main() {
	var a []string
	a = make([]string, 5, 5)
	a[0] = "A"
	a[1] = "B"
	a[2] = "C"
	a[3] = "D"
	a[4] = "E"
	fmt.Printf("a array %#v\n", a)

	s := make([]string, len(a))
	copy(s, a)
	s[2] = "Z"
	fmt.Printf("s array %#v\n", s)
	fmt.Printf("a array %#v\n", a)
}

https://play.golang.org/p/iWAA_LKyjmG