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]
}

猜你喜欢

转载自blog.csdn.net/weixin_36302575/article/details/85784631