【Go】詳解Go的陣列與切片
11. Go 陣列
陣列是指包含同一型別元素的集合,Go不允許陣列混合不同的資料型別
11.1 陣列的詭異宣告語法
var arr [3] int //宣告但不初始化,Go會根據資料型別賦予預設初始化值0 // [0,0,0] var arr = [3]int{5,8,9} //宣告並且初始化 // [5,8,9] var arr = [...]int{5,8,9} //宣告並且初始化,忽略陣列元素個數,Go根據{}內元素個數自動賦予陣列長度 //[5,8,9] // 使用:=簡潔大法 arr := [3]int{12} //自動將剩下的未初始化的值賦予預設值0 //[12,0,0] a := [...]int{12, 78, 50}
11.2 陣列長度 len(arr)
11.3 使用range遍歷陣列
for index,value := range arr {
...
}
for _,value := range arr { //忽略陣列下標
...
}
11.4 多維陣列
arr := [3][2]string{
{"A","B"},
{"a","b"},
{"1","2"},
}
12. Go 切片
因為在Go中陣列是定長的,所以不定長的切片比陣列更常用。切片本身不擁有任何資料,是對現有陣列的引用。
切片宣告與陣列型別,區別在於一個有長度一個沒有長度。
12.1 切片宣告
12.1.1
var myslice []int //宣告切片但不賦值 myslice=nil
12.1.2
myslice := []int{6,7,8}
//與陣列宣告類似,但不寫明長度。
//此時創造了陣列[6,7,8]並返回了myslice對該陣列的引用 len(myslice)為3 cap(mysplice)為3
12.2 對現有陣列的引用,假定現有陣列 arr := [...]int{0,1,2,3,4,5,6,8}
//12.2.1 var myslice [] int = arr[1:4] //代表擷取陣列arr下標1至4-1 [1,2,3] //12.2.2 myslice := arr[1:4] //12.2.2 myslice := arr[:] //表示對arr陣列的全部引用
因為切片是對現有陣列的引用,所以改變切片,被引用的陣列也會改變
12.3
len(myslice) //表示切片的長度 例如arr[1:4] 返回值為3
cap(myslice) //表示切片的容量 例如arr[1:4] 返回值為 len(arr) - startIndex // 7
12.4 使用make建立切片
func make([]T,len,cap) []T {...}
myslice := make([]int,5,5) //[0,0,0,0,0] cap引數可選,預設為len
12.5 追加切片元素
func append(s[]T,x...T) []T {...}
myslice = append(myslice,10)
12.6 多維切片:與多維陣列類似,只要不宣告長度即可
mysplice := [][]string{
{"A","B"},
{"a","b"},
{"1","2"},
}
//如何迴圈輸出多維切片/多維陣列
for _, v1 := range mysplice {
for _, v2 := range v1 {
fmt.Printf("%s ", v2)
}
fmt.Printf("\n")
}
12.7 記憶體優化
參考連結:https://studygolang.com/articles/12121
切片持有對底層陣列的引用。只要切片在記憶體中,陣列就不能被垃圾回收。在記憶體管理方面,這是需要注意的。
讓我們假設我們有一個非常大的陣列,我們只想處理它的一小部分。然後,我們由這個陣列建立一個切片,並開始處理切片。
這裡需要重點注意的是,在切片引用時陣列仍然存在記憶體中。一種解決方法是使用 copy 函式 func copy(dst,src[]T)int 來生成一個切片的副本。這樣我們可以使用新的切片,原始陣列可以被垃圾回收。
package main
import (
"fmt"
)
func countries() []string {
countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}
neededCountries := countries[:len(countries)-2]
countriesCpy := make([]string, len(neededCountries))
copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy
return countriesCpy
}
func main() {
countriesNeeded := countries()
fmt.Println(countriesNeeded)
}
12.8 將切片傳入可變引數函式中
func find (num int,nums ...int){
...
}
func main(){
mysplice := []int{5,8,9}
find(0,mysplice...)
}
tips:在函式體內對形參切片現有的元素進行改變,實參切片也會改變,但是對形參切片進行追加元素,實參切片無變化
Go語言的引數傳遞都是值傳遞。切片包含三部分:長度,容量,指向陣列的第n個元素的指標
當切片作為引數傳遞過去(注意是值傳遞),此時拷貝了一份切片副本(在函式體內使用的就是切片副本)。
然而不管是原切片還是切片副本,其內的元素是指標指向,指向同一個地址,所以我們對切片副本現有的元素做修改,原切片也會變化
但是我們對副本切片做修改,如append,並不會影響原切片