温馨提示:
本文最后更新于
2023-1-12,已超过半年没有更新,若内容或图片失效,请留言反馈。
数组(Array) - 定义说明
在 Golang 中数组是一个 值类型。如果将数组作为函数的参数类型,则在函数调用时该参数将发生数据复制。因此,在函数体中无法修改传入的数组的内容,因为函数内操作的只是所传入数组的一个副本。
我简单描述下数组的使用姿势和演示说明
package main
import "fmt"
func main() {
/*
1) 四种初始化数组的方式
var arr1 [3]int = [3]int{1, 2, 3}
var arr2 = [3]int{1, 2, 3}
var arr3 = [...]int{1, 2, 3} // 程序自动判断数组长度
var arr4 = [3]string{1: "tom", 2: "marry", 0: "jack"}
2) 常规遍历数组
var arr = [3]int{1, 2, 3}
for i := 0; i < len(arr); i++ {
...
}
3) for-range 结构遍历数组
var arr = [3]int{1, 2, 3}
for index, value := range arr {
...
}
说明
1. 第一个返回值 index 是数组的下标
2. 第二个 value 是该下标位置对应的值
3. 他们都是仅在 for 循环内部可见的局部变量
4. 遍历数组元素的时候, 如果不想使用下标 index, 可以直接把下标 index 标为下划线 _ 表示
*/
var (
arr [5]int // 数组长度是定长的(固定的), 当我们定义完数组后, 数组的各个元素的默认值都是0
)
arr[0], arr[1], arr[2], arr[3], arr[4] = 2, 3, 10, 21, 23
arrValue := 0
for i := 0; i < len(arr); i++ {
arrValue += arr[i]
}
fmt.Println(arrValue) // 输出: 59
}
数组使用的注意事项和细节
- 数组是多个 相同类型 数据的集合, 一个数组一旦声明/定义, 其 长度是固定的, 不能动态变化。(如果要动态变化, 可以使用切片)
- 数组中的元素可以是任何数据类型, 包括值类型和引用类型, 但是 不能混用。
- 数组创建后, 如果没有赋值, 有默认值(
零值
)。- 数组的下标都是从
0
开始的- 数组的下标必须在指定的范围内使用, 否则报
panic
数组越界, 比如:var arr [5]int 则有效下标为 0-4
- Go 的数组属 值类型, 在默认情况下是
值传递
, 因此会进行值拷贝
, 数组间不会相互影响。- 如果想在其他函数中去修改原来的数组值, 可以使用引用传递(指针方式) - [可以自行了解下栈原理], 例如:
var arr [3]int
func updateArr(arr [3]int) {
(arr)[0] = 10 // arr[0] = 10
}
updateArr(&arr) // 此时 arr 变量的内容为 {10, 0, 0}, 通过指针方式将数组数据修改- 长度是数组类型的一部分, 在传递函数参数的时候, 需要考虑数组的长度。
从使用上来说没有什么难度, 在这也就不细说, 我将把重点放在内存原理上。
我们看看上述代码的数组在内存里是怎么存放的
从上面的内存图我们可以看到:
数组变量 arr
的内存地址和数组下标为0
的内存地址是一样的, 由此分析出 数组的第一个元素内存地址就是数组变量的内存地址, 这个应该不会太难理解, 因为数组的第一个元素标志着该数组的存在。-
可以看到这5个元素的内存地址其实是有规律的
元素10xc00001a0c0
元素20xc00001a0c8
元素30xc00001a0d0
元素40xc00001a0d8
元素50xc00001a0e0
尾数都是 0 和 8, 当尾数到 8 时, 前位数 进1, 比如 c 进 d, 2 进 3 ...
主要原因就是因为 int 类型是 8字节 的。如果数组是其他的数据类型也是一样, 根据不同的数据类型占用的字节数 满字节后进1。 (例如: int8 是占用1个字节, int16 是占用2个字节, string 是占用16个字节, 你可以通过unsafe.Sizeof(arr)
函数查看字节占用)
如果有第六个元素, 那么它的地址应该是0xc00001a0e8
。
好了, 就先介绍到这。
评论一下?