这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战
使用make分配地址
回到分配。 内置函数 make(T, args) 的用途不同于 new(T)。 它只创建切片、映射和通道,并返回一个类型为 T(不是 *T)的初始化(非零)值。 区别的原因是这三种类型,必须在使用前进行初始化的。 例如,切片是一个三项描述符,包含指向数据(在数组内)、长度和容量的指针,并且在这些项被初始化之前,切片为 nil。 对于切片、映射和通道,make 会初始化内部数据结构并准备要使用的值。
make([]int, 10, 100)
复制代码
分配一个包含 100 个整数的数组,然后创建一个长度为 10、容量为 100 的切片结构,指向数组的前 10 个元素。 (制作切片时,容量可以省略;有关更多信息,请参阅切片部分。)相比之下,new([]int) 返回指向新分配的、归零的切片结构的指针,即指向 零切片值。
这些示例说明了 new 和 make 之间的区别。
var p *[]int = new([]int) // allocates slice structure; *p == nil; 几乎没有用
var v []int = make([]int, 100) // the slice v now refers to a new array of 100 ints
// 没必要的写得复杂:
var p *[]int = new([]int)
*p = make([]int, 100, 100)
// 理想写法:
v := make([]int, 100)
复制代码
请记住, make 仅适用于map、切片和通道,并且不返回指针。 使用 new 获得显式指针分配或显式获取变量的地址。
Arrays
数组在规划内存的详细布局时很有用,有时可以帮助避免分配,但主要是它们是切片的构建块,这一节其实是为了为下一节主题奠定基础,这里有一些关于数组的词。
Go 和 C 中数组的工作方式有很大的不同。在 Go 中,
- 数组是值。 将一个数组分配给另一个会复制所有元素。
- 特别是,如果你将一个数组传递给一个函数,它会收到一个数组的副本,而不是一个指向它的指针。
- 数组的大小是其类型的一部分。 [10]int 和 [20]int 类型是不同的。
值属性可能很有用,但代价也很昂贵; 如果你想要类似 C 的行为和效率,你可以传递一个指向数组的指针。
func Sum(a *[3]float64) (sum float64) {
for _, v := range *a {
sum += v
}
return
}
array := [...]float64{7.0, 8.5, 9.1}
x := Sum(&array) // Note the explicit address-of operator
复制代码
但即使是这种风格也不是理想 Go的使用方式。 请改用切片。