Go语言中的数组大概相当与C/C++中的数组,固定大小,不能够动态扩展大小,而切片大概相当与C++中的Vector,可以动态扩展大小,当大小超过容量时,重新分配一块内存,然后将数据复制到新的内存区域。下面我们通过几个问题来更好理解golang 的数组和切片,一起来看看吧。 在Go语言中,数组和切片是两种非常重要的数据结构,它们在编程中扮演着不同的角色。本篇文章将深入探讨Go语言中的数组和切片,帮助你更好地理解和使用这两种数据结构。 数组是一种固定大小的数据集合,其长度在声明时必须指定且不可更改。在Go语言中,数组是值类型,这意味着当你将一个数组赋值给另一个变量时,实际上是进行了一次值拷贝。因此,修改其中一个数组不会影响另一个。下面的示例展示了这一点: ```go a := [3]int{1, 2, 3} b := a // b 是 a 的一份拷贝 c := a[:] // c 是一个切片,引用 a 的底层数组 ``` 当我们修改 a 的值时,b 不变,而 c 的值会相应改变,因为 c 是引用类型。 切片则更像C++中的动态数组或Vector,它可以动态地扩展和收缩。切片是一个指向数组的引用,它包含三个部分:底层数组的指针、长度和容量。使用 `make` 函数可以创建一个切片,如下所示: ```go s1 := make([]int, 0, 3) ``` 切片可以通过 `append` 函数添加元素,如果添加的元素数量超过了底层数组的容量,Go语言会自动创建一个新的更大的数组,并将原有数据复制过去。这种机制使得切片能够灵活地处理动态数据集。 ```go s1 := make([]int, 0, 3) for i := 0; i < cap(s1); i++ { s1 = append(s1, i) } s2 := s1 // s2 引用 s1 的底层数组 ``` 当我们修改 s1 的值时,由于 s2 也是引用 s1 的底层数组,所以 s2 的值也会随之改变。 关于 `append` 操作超出底层数组界限的情况,如果切片的长度增加,会导致底层数组无法容纳新元素,Go语言会创建新的数组并将旧数组的所有元素复制过来。以下示例展示了这一过程: ```go n1 := [3]int{1, 2, 3} n2 := n1[0:3] // ... n2 = append(n2, 1) ``` 在此过程中,n2 之前和之后的地址对比可以看出,超出底层数组n1的界限后,n2 将引用新的数组。 讨论一下切片引用“失效”的问题。在Go中,如果通过切片的引用修改了切片本身(例如,通过重新分配切片的长度),那么原始的引用将不再指向原来的底层数组。下面的 `rmLast` 函数尝试删除切片的最后一个元素,但并没有实际修改原切片: ```go func rmLast(a []int) { // ... a = a[:len(a)-1] } ``` 在 `main` 函数中,`rmLast(xyz)` 调用后,`xyz` 的地址并未改变,因为函数内部的 `a` 是对 `xyz` 的副本,对副本所做的修改不会影响原始切片。 总结来说,Go语言中的数组是固定大小的值类型,而切片则是动态的引用类型。理解这两种数据结构的区别和使用场景对于编写高效的Go代码至关重要。在处理静态数据时,数组可能是更好的选择;而在需要动态调整大小的数据集时,切片则更为合适。同时,注意在使用切片时,对切片的操作可能会影响到底层数组,而修改切片本身并不改变原始引用。
- 粉丝: 8
- 资源: 950
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助