Effective Go : 数据(二)

这是我参与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的使用方式。 请改用切片。

猜你喜欢

转载自juejin.im/post/7034825714742329351