# Day 11 : Golang Slice (2)
## 前言
在第一篇slice的文章,slice本身是不會儲存任何值,而是透過指針指向底下的陣列,代表這個slice是要從陣列哪個index開始,並記錄slice自己的長度(len)與容量(cap),且如果要更改slice裡面的元素,其實是修改底下隱藏的陣列。
這時可以想到,之前提到陣列是有固定長度,不能新增或修改,而slice是可以隨時新增刪除,那麼當我們一值新增slice元素時,其大小會超過底下的隱藏陣列(len>cap)時會怎麼辦呢? 這時候Go會在底層建立一個更大的陣列,將舊陣列的內容複製到新陣列,在把slice的指標指向這個新陣列。
## 實際練習
接下來用append和copy來學習是否有新增陣列的差異。
1. 單純新增slice,指向同一個底層的陣列。
s2是直接複製slice,所以是會產生一個新的slice,指向和s1一樣的底層array(將s1儲存的位置給s2)
s3建立一個新的slice,範圍是s1的第一個元素到最後一個元素,指向同一個陣列
```go=
func main() {
a1, a2, a3 := linked()
fmt.Println(a1) // 99
fmt.Println(a2) // 99
fmt.Println(a3) // 99
}
func linked() (int, int, int) {
s1 := []int{1, 2, 3, 4, 5}
s2 := s1
s3 := s1[:]
fmt.Printf("s1 底層的陣列的記憶體位置:%p\n", &s1[0]) // 0xc00000e420
fmt.Printf("s2 底層的陣列的記憶體位置:%p\n", &s2[0]) // 0xc00000e420
fmt.Printf("s3 底層的陣列的記憶體位置:%p\n", &s3[0]) // 0xc00000e420
s2[3] = 99
return s1[3], s2[3], s3[3]
}
```
2. 新增元素,會超過原本slice的容量,會創造新的陣列
當在第12行append新值的時候,會超過原本s1的容量,創造新的底層陣列,並將s1指向新的底層陣列。故之後透過`s1[2]=99`修改元素後,s2因為指向原本的底層陣列,所以值不會變,s1會指向新的底層陣列,所以s1[2]是99。
```go=
func main() {
b1, b2 := noLink()
fmt.Println("b1",b1) // 99
fmt.Println("b2",b2) // 3
}
func noLink() (int, int) {
s1 := []int{1, 2, 3, 4, 5} // len : 5 cap : 5
s2 := s1
fmt.Printf("s1: %p\n", &s1[0]) // s1 : 0xc00000e420
fmt.Printf("s2: %p\n", &s2[0]) // s2 : 0xc00000e420
s1 = append(s1, 6)
fmt.Printf("s1: %p\n", &s1[0]) // s1 : 0xc000010280
fmt.Printf("s2: %p\n", &s2[0]) // s2 : 0xc00000e420
s1[2] = 99
return s1[2], s2[2]
}
```

(圖一,自行繪製)
3 `copy(<目標的slice>,<來源的slice>)`。透過copy將s1裡面的元素複製到s2中,因為s1和s2是指向不同底層的陣列,所以單純對s1的修改不會影響到s2。
```go=
func main() {
c1, c2, c3 := copyFunc()
fmt.Println("c1", c1) // 99
fmt.Println("c2", c2) // 4
fmt.Println("c3", c3) // 5, 代表複製了5個變數
}
func copyFunc() (int, int, int) {
s1 := []int{1, 2, 3, 4, 5}
s2 := make([]int, 5)
fmt.Printf("s1: %p\n", &s1[0]) // 0xc00000e420
fmt.Printf("s2: %p\n", &s2[0]) // 0xc00000e450
copied := copy(s2, s1)
fmt.Printf("s1: %p\n", &s1[0]) // 0xc00000e420
fmt.Printf("s2: %p\n", &s2[0]) // 0xc00000e450
s1[3] = 99
return s1[3], s2[3], copied
}
```
## References
1. [良葛格-底層為陣列的 slice](https://openhome.cc/Gossip/Go/Slice.html)
###### tags: `About Go`