Go語言入門4-切片slice
阿新 • • 發佈:2019-01-07
切片slice
其本身並不是陣列,它指向底層的陣列
作為變長陣列的替代方案,可以關聯底層陣列的區域性或全部
為引用型別
- 可以直接建立或從底層陣列獲取生成
func main() {
// var s1 []int
// fmt.Println(s1) []
a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(a) //[1 2 3 4 5 6 7 8 9 0]
s1 := a[5:10] //取陣列a中索引5到10的值,包含5,但是不包含10
s2 := a[5:len(a)] //len(a)為陣列的長度
s3 := a[5:]
s4 := a[:5] //取前五個值
fmt.Println(s1) //[6 7 8 9 0]
fmt.Println(s2) //[6 7 8 9 0]
fmt.Println(s3) //[6 7 8 9 0]
fmt.Println(s4) //[1 2 3 4 5]
}
- 一般使用make()建立
func main() {
s1 := make([]int, 10,10)
//引數為:型別,包涵多少元素,初始容量,
//如果包含的元素超過容量,比如有11個元素,
//那麼就會重新分配一個容量為20( 初始容量翻倍)的記憶體快
}
- 使用len()獲取元素個數,cap()獲取容量
func main() {
s1 := make([]int, 3, 10)
fmt.Println(s1) //[0 0 0]
fmt.Println(len(s1)) //3
fmt.Println(cap(s1)) //10
}
- 如果多個slice指向相同底層陣列,其中一個的值改變會影響全部
func main() {
a := []int{1, 2, 3, 4, 5}
s1 := a[2:5]
s2 := a[1:3]
fmt.Println(s1, s2) //[3 4 5] [2 3]
s1[0] = 9
fmt.Println(s1, s2) //[9 4 5] [2 9]
}
Reslice(從一個slice中獲得另一個slice)
- Reslice時索引以被slice的切片為準
func main() {
a := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}
sa := a[2:5]
sb := a[3:5] //在原陣列a上取
sb2 := sa[1:3] //在切片sa上取
fmt.Println(string(sa)) //cde
fmt.Println(string(sb)) //de
fmt.Println(string(sb2)) //de
}
- 索引不可以超過被slice的切片的容量cap()值
- 索引越界不會導致底層陣列的重新分配而是引發錯誤
func main() {
a := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}
sa := a[2:5]
fmt.Println(len(sa), cap(sa)) //3 9
sb := a[3:5] //在原陣列a上取
sb2 := sa[1:3] //在切片sa上取
sb3 := sa[3:5]
sb4 := sa[9:11] //超過了容量cap()值
fmt.Println(string(sa)) //cde
fmt.Println(string(sb)) //de
fmt.Println(string(sb2)) //de
fmt.Println(string(sb3)) //fg
fmt.Println(string(sb4)) //索引越界 slice bounds out of range
}
Append追加
- 可以在slice尾部追加元素
- 可以將一個slice追加在另一個slice尾部
- 如果最終長度未超過追加到slice的容量則返回原始slice
- 如果超過追加到的slice的容量則將重新分配陣列並拷貝原始資料
func main() {
s1 := make([]int, 3, 6)
fmt.Printf("%p\n", s1)
s1 = append(s1, 1, 2, 3)
fmt.Printf("%v %p\n", s1, s1)
s1 = append(s1, 1, 2, 3)
fmt.Printf("%v %p\n", s1, s1)
}
結果:
0xc420078000
[0 0 0 1 2 3] 0xc420078000
[0 0 0 1 2 3 1 2 3] 0xc42007e000 //注意此時超過容量了,重新分配了所以地址變了
- 在同一個底層陣列上的修改會影響到所有的slice,但如果append後如果超出容量後,只會影響當前的slice
func main() {
a := []int{1, 2, 3, 4, 5}
s1 := a[2:5]
s2 := a[1:3]
fmt.Println(s1, s2) //[3 4 5] [2 3]
s2 = append(s2, 888, 888, 888, 888, 888, 888)
s1[0] = 9
fmt.Println(s1, s2) //[9 4 5] [2 3 888 888 888 888 888 888]
}
Copy 追加
func main() {
s1 := []int{1, 2, 3, 4, 5, 6}
s2 := []int{7, 8, 9}
copy(s1, s2) //把s2copy到s1中
fmt.Println(s1) //[7 8 9 4 5 6]
fmt.Println(s2) //[7 8 9]
}
func main() {
s1 := []int{1, 2, 3, 4, 5, 6}
s2 := []int{7, 8, 9}
copy(s2, s1)
fmt.Println(s1) //[1 2 3 4 5 6]
fmt.Println(s2) //[1 2 3]
}
把指定的值copy到指定的位置
func main() {
s1 := []int{1, 2, 3, 4, 5, 6}
s2 := []int{7, 8, 9}
copy(s1[2:4], s2[0:2])
fmt.Println(s1) //[1 2 7 8 5 6]
fmt.Println(s2) //[7 8 9]
}