Go語言的Slice(切片)是用來描述array(陣列)區段的參照,本身不儲存值,長度可變。
Slice的用途類似Java的ArrayList
,其背後都是陣列,大小可動態增加,裝載連續多個同型態的元素。
Slice用來表示array的一個區段,語法為array變數後加上[low:high]
取得,low
及high
代表截取陣列的始末index位置,含起始元素但不含結束元素。如果起始index為第一個位置或結束index為最後一個位置的下一個位置可省略。起始index相同則截取0個元素。
a := [5]string{"a", "b", "c", "d", "e"} // 宣告陣列變數a及賦予元素值
s := a[1:3]
fmt.Println(s) // [b c]
s = a[:3] // 相當於a[0:3]
fmt.Println(s) // [a b c]
s = a[3:] // 相當於a[3:5]
fmt.Println(s) // [d e]
s = a[1:1] // 截取0個元素
fmt.Println(s) // []
截取index的值不可為負,不可超過元素長度,起始index要小於結束index,否則編譯錯誤。
a := [5]string{"a", "b", "c", "d", "e"} // index from 0-4
s := a[-1:] // invalid slice index -1 (index must be non-negative)
s = a[:6] // invalid slice index 6 (out of bounds for 5-element array)
s = a[3:1] // invalid slice index: 3 > 1
除了從array截取,也可用slice literal語法宣告slice及賦值,語法類似arrays literal但不在方括弧設定長度。
s := []string{"a", "b", "c", "d", "e"} // slice literal
fmt.Println(s) // [a b c d e]
相當於宣告陣列在截取整段array為slice。
a := [5]string{"a", "b", "c", "d", "e"}
s := a[:] // 截取開頭到最後位置的slice
fmt.Println(s) // [a b c d e]
Slice僅是array的參照而不儲存值,因此當兩個slice參照同個array的元素被異動時都會被影響。
a := [5]string{"a", "b", "c", "d", "e"}
s1 := a[:3] // [a b c]
s2 := a[2:] // [c d e]
a[2] = "X"
fmt.Println(s1) // [a b X]
fmt.Println(s2) // [X d e]
Slice除了長度(length)外有容量(capacity)。
length代表slice所包含的元素數量,使用內建函數len(ss)
取得;
capacity代表從slice第一個參照index位置起算的array長度,使用內建函數cap(s)
取得。
a := [5]string{"a", "b", "c", "d"} // 第五個元素為空字串""
fmt.Println(len(a)) // 5
s := a[1:3] // [b c]
fmt.Println(len(s)) // 2, slice所含元素的個數
fmt.Println(cap(s)) // 4, 從slice的第一個參照'b'位置起算到array最後位置的長度
一個slice的來源若為另一個slice,參照的仍是同個array。
a := [5]string{"a", "b", "c", "d", "e"}
s1 := a[:3] // [a b c]
fmt.Println(cap(s1)) // 5
s2 := s1[2:]
fmt.Println(s2) // [c]
fmt.Println(cap(s2)) // 3, count from index of "c" to final index of array a
宣告空slice的語法為[]T
,後接的T
代表元素型態。例如下面宣告一個型態為int
的空slice變數s
。length及capacity皆為0代表沒有參照任何array,所以為nil
。
var s []int
fmt.Println(s) // []
fmt.Println(len(s)) // 0
fmt.Println(cap(s)) // 0
fmt.Println(s == nil) // true
若slice的length為0但capacity不為0則不為nil
。
a := [5]string{"a", "b", "c", "d", "e"}
s := a[0:0]
fmt.Println(len(s)) // 0
fmt.Println(cap(s)) // 5
fmt.Println(s == nil) // false
若要建立一個指定長度的空slice,使用內建函式make([]T, length, capacity)
,第一個參數[]T
為slice資料型態,第二個參數length
為slice長度,第三個參數capacitiy
為參考的陣列的長度。
s = make([]int, 5)
fmt.Println(s) // [0 0 0 0 0]
fmt.Println(len(s)) // 5
fmt.Println(cap(s)) // 5
上面以make()
建立的slice相當於以下先建立array在截取slice。
s := new([5]int)[:] // create an array with length 5 then get slice
fmt.Println(s) // [0 0 0 0 0]
fmt.Println(len(s)) // 5
fmt.Println(cap(s)) // 5
加入新元素到slice可使用內建函式append(s S, x ...T) S
加入新的元素。如果原參照的array空間不足則會將內容複製到到另一個更大空間的array並重新參照。
s := make([]int, 3)
fmt.Println(s) // [0 0 0]
fmt.Println(len(s)) // 3
fmt.Println(cap(s)) // 3
s = append(s, 1) // add new element
fmt.Println(s) // [0 0 0 1]
fmt.Println(len(s)) // 4
fmt.Println(cap(s)) // 6, reallocated array length
複製slice到另個可使用內建函式copy(dst, src []T) int
,參數dst
為複製目標slice,src
為複製來源slice,複製目標及來源的型態必須相同。返回值代表複製的元素個數。
src := []int{1, 2, 3, 4, 5}
dst := make([]int, 3)
fmt.Println(dst) // [0 0 0]
n := copy(dst, src)
fmt.Println(dst) // [1 2 3]
fmt.Println(n) // 3, the numbers of elemnets copied
使用range
走訪slice如下,回傳的第一個值i
為元素的index,第二個值v
為元素的值。
s := []string{"a", "b", "c", "d", "e"}
for i, v := range s {
fmt.Printf("index=%d, value=%s\n", i, v)
}
執行印出如下:
index=0, value=a
index=1, value=b
index=2, value=c
index=3, value=d
index=4, value=e
沒有留言:
張貼留言