Go 中通过 new(Type) 和 &Type{} 分配内存的区别

Obj*_*ive 2 go

考虑以下示例:

type House struct{}

func main() {
    house1 := new(House)
    house2 := &House{}
    fmt.Printf("%T | %T\n", house1, house2)
}
Run Code Online (Sandbox Code Playgroud)

输出:*main.House | *main.House

两个赋值都会生成一个指向类型的指针House(来自包 main)。

来自 go 文档new

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
Run Code Online (Sandbox Code Playgroud)

两个作业中的内存分配在技术上是否相同?有最佳实践吗?

bla*_*een 5

两个作业中的内存分配在技术上是否相同?

我不会谈论实现细节,因为这些细节可能会改变,也可能不会改变。

从语言规范的角度来看,是有区别的。

分配遵循分配new(T)规则(我自己的注释[斜体]):

内置函数new采用 type T,在运行时为该类型的变量分配存储空间,并返回*T指向该类型的值。该变量按照初始值部分中的描述进行初始化。[其零值]

使用复合文字进行分配时,遵循复合文字寻址&T{}的规则:

复合文字为结构体、数组、切片和映射构造值,并在每次计算它们时创建一个新值。

获取复合文字的地址会生成一个指向用文字值初始化的唯一变量的指针。

因此new(T)和 都&T{}分配存储并产生类型 的值*T。然而:

  • new(T)接受任何类型,包括预先声明的标识符 asintbool,如果您只需要使用一行初始化此类变量,这可能会派上用场:
n := new(int) // n is type *int and points to 0
b := new(bool) // b is type *bool and points to false
Run Code Online (Sandbox Code Playgroud)
  • new引用Effective Go)“不会初始化1该内存,它只会将其归零”。即内存位置将具有类型的零值。
  • 复合文字只能用于结构体、数组、切片和映射
  • 复合文字可以通过显式初始化结构体字段或数组/切片/映射项来构造非零值

底线:正如Effective Go 所指出的(与上面的段落相同):

如果复合文字根本不包含任何字段,它会为该类型创建零值。表达式new(T)&T{}是等效的。


[1]:规范和Effective Go 中术语“初始化”的使用不一致。要点是,new您只能产生零值,而复合文字允许您构造非零值。显然,规格才是真相的来源。