Go語言入門4-切片slice

切片slice

其本身並不是數組,它指向底層的數組
作爲變長數組的替代方案,可以關聯底層數組的局部或全部
爲引用類型

  1. 可以直接創建或從底層數組獲取生成
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]
}
  1. 一般使用make()創建
func main() {
	s1 := make([]int, 1010)		
	//參數爲:類型,包涵多少元素,初始容量,
	//如果包含的元素超過容量,比如有11個元素,
	//那麼就會重新分配一個容量爲20( 初始容量翻倍)的內存快
}
  1. 使用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
}
  1. 如果多個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)

  1. 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
}
  1. 索引不可以超過被slice的切片的容量cap()值
  2. 索引越界不會導致底層數組的重新分配而是引發錯誤
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追加

  1. 可以在slice尾部追加元素
  2. 可以將一個slice追加在另一個slice尾部
  3. 如果最終長度未超過追加到slice的容量則返回原始slice
  4. 如果超過追加到的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 //注意此時超過容量了,重新分配了所以地址變了

  1. 在同一個底層數組上的修改會影響到所有的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]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章