golang的数组
数组
数组的价值
在编程中,常常会需要处理一堆同类事物,并对每个个体都有记录要求的时候,此时,如果采用传统方法(一个个体对应一个变量),那就需要定义大量的变量,这严重影响了代码的可读性和可维护性。
此时,就是数组大展身手的时刻,数组能够轻松的记录大量同类事物
数组的介绍
数组可以存放多个同一类型的数据,数组也是一种数据类型,在go中数组是值类型
fmt.Printf(“%v\n”, hen)的输出结果为:[3 4 5 6 7 8]。这也明确表示数组是值类型,直接返回的是数组的值。
数组的快速入门
func main() {
var hen [6]float64
var sum float64
for i := 0; i < len(hen); i++ {
hen[i] = 3.0 + float64(i)
sum += hen[i]
}
fmt.Printf(“%v”, sum/float64(len(hen)+1))
}
用于处理求平均问题
数组定义
var 数组名[数组大小]数据类型
var a[5]int
数组的内存布局
数组名就是数组的首地址,也就是数组第一个元素的地址
fmt.Printf(“%p,%p,%p,%p”, &hen, &hen[0], &hen[1], &hen[2])
返回的结果是:0xc00000c4b0,0xc00000c4b0,0xc00000c4b8,0xc00000c4c0
可见&hen, &hen[0]这两个的值一样。
亦可见,数组的地址其实是连续的,因为float64是8个字节,所以每下一个元素的地址,就会在上一个元素的地址上+8;同理,如果是float32,那就是在上一个元素的地址的基础上+4
数组的使用
当要查询数组a的第i个元素时,使用a[i-1]的形式获取
因为数组在使用时是调用索引(下标的),而第i个元素对应的下标是i-1
四种初始化数组的方式
- var a [3]int =[3]int {1,2,3}
- var a =[3]int {1,2,3}
- var a =[…]int {1,2,3}
- var name = [3]string {1:“tom”,0:“lsh”,2:“zjw”}
数组的遍历
- 传统用for语句
- go中的for-range语句
基本语法:
for index,value :=range array{
…
}
第一个返回值index是数组的下标
value是该下标的值
index和value都是只在for循环内部可见的局部变量
遍历数组元素时,如果不想使用index,可以用下划线(占位符)代替
index和value不是固定的,程序员可以自己决定,但一般是这样的
数组使用的细节和注意事项
- 数组是多个相同数据类型数据的组合,一个数组一旦声明/定义了,其长度就是固定不变的,不能动态变化
- var a []int,此时的a是一个切片。如果是数组的话,那中括号内必须要有这个数组的大小
- 数组中的元素可以是任何类型,包括值类型和引用类型,但是只能是相同的类型
- 数组创建后,如果没有初始化赋值,就存储默认值
int,float系列默认值0
bool默认值false
string默认值""(空字符串) - 使用数组的流程:
- 声明数组并开辟空间
- 给数组各个元素赋值(不赋值就是默认值)
- 使用数组
- 数组的下标是从0开始
- 数组下标必须在范围内使用,否则会报panic:数组越界
比如说,如果数组的大小是10,那么下标的范围就是0-9
- go中的数组是值类型,在一般情况下是值传递,因此会进行值拷贝,也就是说,当把数组传入函数时,函数内部的代码无法对函数外部这个数组的值产生影响
代码示例:
func test(arr [3]int) {小知识点:在golang中,arr [3]int和arr [4]int完全是两个东西,所以在传入数组时,切忌要加上数组长度
arr[0] = 2
dizhi := &arr[1]
*dizhi = 10
}
func main() {
var arr [3]int
arr[0] = 1
arr[1] = 3
arr[2] = 2
test(arr)
fmt.Println(arr)
}
输出结果为:[1 3 2]
显然,函数内部哪怕通过地址也无法改变传入的数组的值。
原因:
因为在go中,在向函数传入数组时,系统内存会在栈中划分出一块给这个函数的空间,在这个空间自动浅拷贝一个内容一模一样,但是地址不同的数组。也就是和传入int,float系列一样的效果
- 如果非要在函数中改变外部数组的值,那么只能通过传引用类型(指针)的方式,比如说数组的地址
- 在go中,长度是数组类型的一部分,在传递函数时,一定要带上长度。同第8点中高亮的小知识点