Golang亿点小细节之slice

@Golang亿点小细节之切片
你所忽略的,往往才是Bug的起源

谨言

不会slice,请不要尝试用go写算法!

简单聊聊slice

slice是一个长度可变的数组
go提供给slice的主要方法包括有切片[:],重组[:len()+n],复制copy(),追加append()
slice的三个部分:指向相关数组的指针ptr、当前数组长度len、相关数组最大容量cap
Golang亿点小细节之slice_第1张图片
在开始下面的内容前,请把这个图记在脑子里!

首先我们先来聊聊切片操作

x:=[]int{2,3,5,7,11}
y:=x[1:3]   //y是通过对x进行切片得到的

但是切片不是进行拷贝,谨记,看图
Golang亿点小细节之slice_第2张图片
切片操作是将产生的slice的ptr指向原slice的相关数组,同时通过lencap产生一个形式上的切片

接下来聊聊重组和复制

改变slice长度的过程叫做重组

sl = sl[0:len(sl)+1]

slice重组只是改变了len的值,切片可以反复扩展直到占据整个相关数组,即len=cap,当len>cap是就会发生扩容,扩容是使ptr重新指向一个更大的相关数组
slice复制
func copy(dst, src []T) int copy
将类型为 T 的切片从源地址 src 拷贝到目标地址 dst,覆盖 dst 的相关元素,并且返回拷贝的元素个数。一般情况下复制可以使得两个slice拥有相互独立的相关数组。不过,源地址和目标地址可能会有重叠

我愿称append()是go最大的坑

先给大家上一段代码

package main

import "fmt"

func main() {
	x :=[]int{2,3,5,7,11}
	y := x[1:3]
	fmt.Println(y)
	y=append(y, 10)
	fmt.Println(y)
	fmt.Println(x)
	/*
	output:
	[3 5]
	[3 5 10]     
	[2 3 5 10 11]  //我的7怎么变成了10?????????
	*/
}

细心的小伙伴会发现7->10,原因是因为y.ptr指向了x[1],所以append()把7给覆盖掉了
在来一段代码

package main

import "fmt"

func main() {
	x :=[]int{2,3,5,7,11}
	y := x[1:]  // 通过修改切片操作的长度,使得y在进行追加时会发生扩容
	fmt.Println(y)
	y=append(y, 10)
	fmt.Println(y)
	fmt.Println(x)
	/*
	output:
	[3 5 7 11]
	[3 5 7 11 10]   
	[2 3 5 7 11]  // 我的7怎么又回来了???????
	*/
}

上文中说到当slice发生扩容时,会重新分配相关数组,所以y的相关数组被重新分配了,但是这并不会影响x

你可能感兴趣的:(golang亿点小细节,go语言)