Golang构造结构体对象new方法和取地址符&的区别
面向对象的语言一般都有构造函数,用来在创建对象时初始化对象,即为对象成员变量赋初始值。但是Golang里面没有构造函数,在初始化结构体对象时可以使用new操作符,也可以使用&操作符,两者具体区别在哪里呢?
一、构造函数与复合语义(Constructors and composite literals)
在go官方文档 effective_go 中的 Constructors and composite literals
章节部分指出:
1 | As a limiting case, if a composite literal contains no fields at all, it creates a zero value for the type. |
也就是说,如果在构造结构体时,复合文本中没有包含任何字段,则它将为类型创建一个零值。此时表达式 new(File) 和 &File{} 是等价的。
有时候零值初始化并不够好,所以构造函数还是有必要的,看 package os 包中的一个例子:
1 | func NewFile(fd int, name string) *File { |
这种类似早期 C++ 生成对象的写法,看着有点繁琐,而且有时候也容易遗漏某些字段。可以使用复合语义来简化,而且每次调用时都是不同的实例。
1 | func NewFile(fd int, name string) *File { |
与 C、C++ 不同,go 语言可以返回局部变量的地址,变量相关联的存储在函数返回后继续存在。合并上述代码的最后两行,进一步简化。
1 | return &File{fd, name, nil, 0} |
复合文本的字段按顺序排列,并且必须全部存在。但是,通过将元素显式标记为 field:value
对,初始化器可以以任何顺序出现。未出现的字段,则使用对应类型的零值初始化。
1 | return &File{fd: fd, name: name} |
二、在赋值语句方面的不同
使用new
1 | package main |
在赋值 = 操作时,虽然 a、b 的地址不同,但是修改了 b 对象的 Name 字段值,a 对象的 Name 字段也改变了。
使用取地址符&
1 | package main |
这里改变 b 变量 Name 字段的值,不会对 a 变量 Name 字段造成影响。若讲赋值语句修改为 b := &a
,即将 b 指向了 a 变量的地址,此时修改 b 的 Name 字段,实际也是在修改 a 变量的 Name 字段。
- 本文标题:Golang构造结构体对象new方法和取地址符&的区别
- 本文作者:beyondhxl
- 本文链接:https://www.beyondhxl.com/post/63e034ab.html
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!