数组初始化方式常用的有3种,至于其它的用的很少,就不用管了,常用方式如下:var a[4]intb := [4]int{2, 4}c := [...]int{2, 4}
Go数组是值类型,赋值和传参会复制整个数组数据,为了避免数据复制,可以使用数组指针:func test(x *[2]int) { x[1] += 1}func main() { a := [2]int{2, 3} test(&a)}
func main() { x,y := 1, 2 a := [...]*int{&x, &y} p := &a }
Go的数组,其实我们用的不多,一般大家都用切片,所以对于数组,掌握上述知识就可以了,其它关于数组的知识,需要用的时候,查阅相关资料即可。2.2 切片
s1 := make([]int, 4, 6)s2 := []int{10,20,30,40,50,60}
s1 := make([]int, 4, 6)的示意图如下,由于 len = 4,所以后面2个暂时访问不到,但是容量还是在,数组里面每个变量都是0 。![]()
s2 := [] int{10,20,30,40,50,60}的示意图如下:![]()
切片的操作符s[i:j:k],j和k是个开区间,详见下图:![]()
2.2.2 nil和空切片
nil切片的指针指向nil,表示一个不存在的切片:空切片一般会用来表示一个空的集合。比如数据库查询,一条结果也没有查到,那么就可以返回一个空切片。silce := make([]int , 0) slice := []int{}
![]()
需要说明的一点:不管是使用 nil 切片还是空切片,对其调用内置函数 append,len 和 cap 的效果都是一样的。然后切片只能和nil判等,不支持切片判等。2.2.3 切片扩容
![]()
Go 切片扩容策略:如果切片的容量小1024个元素,于是扩容的时候就翻倍增加容量。上面那个例子也验证了这一情况,总容量从原来的4个翻倍到现在的8个。一旦元素个数超过1024个元素,那么增长因子就变成 1.25,即每次增加原来容量的1/4。下面我们看一种情况,当扩容时没有新建一个新的数组的情况,这里容易出问题:func main() { array := [4]int{10, 20, 30, 40} slice := array[0:2] newSlice := append(slice, 50) newSlice[1] += 10 }
内部情况见图,可以看出slice、newSlice和array底层共用一个数组,当修改newSlice[1]时,因为底层数据被修改,其它也都被修改了,这样非常容易产生莫名的Bug!![]()
2.2.4 切片遍历
如果用 range 的方式去遍历一个切片,拿到的 Value 其实是切片里面的值拷贝,每次打印 Value 的地址都不变,所以仅修改Value的值,是不会改变Slice中的数据,这点切记!!!![]()