go同构符合类型:定长数组和变长切片
数组
go数组的两个属性:
长度固定
同构元素组成
声明
var arr [N]T
Go 编译器需要在编译阶段就知道数组类型的长度,所以,我们只能用整型数字面值或常量表达式作为 N 值。
如果两个数组类型的元素类型 T 与数组长度 N 都是一样的,那么这两个数组类型是等价的,如果有一个属性不同,它们就是两个不同的数组类型。
func foo(arr [5]int) {} func main() { var arr1 [5]int var arr2 [6]int var arr3 [5]string foo(arr1) // ok foo(arr2) // 错误:[6]int与函数foo参数的类型[5]int不是同一数组类型 foo(arr3) // 错误:[5]string与函数foo参数的类型[5]int不是同一数组类型 }
数组类型不仅是逻辑上的连续序列,而且在实际内存分配时也占据着一整块内存。Go 编译器在为数组类型的变量实际分配内存时,会为 Go 数组分配一整块、可以容纳它所有元素的连续内存,如下图所示:
定义
未显式初始化
不进行显式初始化,那么数组中的元素值就是它类型的零值
var arr1 [6]int // [0 0 0 0 0 0]
显式初始化
var arr2 = [6]int { 11, 12, 13, 14, 15, 16, } // [11 12 13 14 15 16] var arr3 = [...]int { 21, 22, 23, } // [21 22 23] fmt.Printf("%T\n", arr3) // 也可以忽略掉右值初始化表达式中数组类型的长度,用“…”替代,Go 编译器会根据数组元素的个数,自动计算出数组长度
使用下标进行初始化
var arr4 = [...]int{ 99: 39, // 将第100个元素(下标值为99)的值赋值为39,其余元素值均为0 } fmt.Printf("%T\n", arr4) // [100]int
如果下标值超出数组长度范畴,或者是负数,那么 Go 编译器会给出错误提示,防止访问溢出。
多维数组
var mArr [2][3][4]int
总结
数组类型变量是一个整体,这就意味着一个数组变量表示的是整个数组。无论是参与迭代,还是作为实际参数传给一个函数 / 方法,Go 传递数组的方式都是纯粹的值拷。
切片
解决数组的两个不足点:
1.固定的元素个数
2.传值机制下导致的开销较大
声明
var nums = []int{1, 2, 3, 4, 5, 6}
切片有自己的长度,只不过这个长度不是固定的,而是随着切片中元素个数的变化而变化的
添加元素append
nums = append(nums, 7) // 切片变为[1 2 3 4 5 6 7 fmt.Println(len(nums)) // 7