【问题标题】:What's the difference between new(Struct) and &Struct{} in Go?Go 中的 new(Struct) 和 &Struct{} 有什么区别?
【发布时间】:2021-10-31 19:34:23
【问题描述】:

它们似乎是一样的:

package main

import "fmt"

type S struct {
    i int
}

func main() {
  var s1 *S = new(S)
  fmt.Println(s1)

  var s2 *S = &S{}
  fmt.Println(s2)  // Prints the same thing.
}

更新:

嗯。我刚刚意识到没有明显的方法可以使用 new 初始化 S.i。有没有办法做到这一点? new(S{i:1}) 似乎不起作用:/

【问题讨论】:

    标签: go


    【解决方案1】:

    来自Effective Go

    作为一种限制情况,如果复合文字根本不包含任何字段,它会为该类型创建一个零值。表达式new(File)&File{} 是等价的。

    【讨论】:

    • 有没有办法使用 new 初始化字段?
    • @allyourcode 不这么认为。 stackoverflow.com/questions/4498998/…
    • 文档有没有说,为什么他们选择包含new 函数?我以为go 是关于非重叠功能的……
    • @ThomasAhle x := 5 vs var x = 5 vs var x int = 5 vs var x int; x = 5 怎么样?它不乏重复和冗余的方法来做同样的事情,尽管在许多情况下可以提供一组丰富的习语来尽可能准确地表达程序员的意图。
    • 我不确定 Effective Go 是否是 normative,但语言规范相对于 new& {} 而言没有那么简单
    【解决方案2】:

    它们不仅给出相同的结果值,而且如果我们以两种方式分配某些东西并查看它们的值...

    // Adapted from http://tour.golang.org/#30
    package main
    
    import "fmt"
    
    type Vertex struct {
        X, Y int
    }
    
    func main() {
        v := &Vertex{}
        v2 := new(Vertex)
        fmt.Printf("%p %p", v, v2)
    }
    

    ...我们将看到它们实际上是在连续的内存槽中分配的。典型输出:0x10328100 0x10328108。我不确定这是实现细节还是规范的一部分,但它确实表明它们都是从同一个池中分配的。

    Play around with the code here.

    至于用new初始化,根据the language specThe built-in function new takes a type T and returns a value of type *T. The memory [pointed to] is initialized as described in the section on initial values.因为go中的函数不能重载,而且这不是变参函数,所以没有办法传入任何初始化数据。相反,go 将使用对类型和任何成员字段有意义的任何版本的 0 对其进行初始化。

    【讨论】:

      【解决方案3】:
      Case 1: package main
      
      import (
          "fmt"
      )
      
      type Drink struct {
          Name    string
          Flavour string
      }
      
      func main() {
          a := new(Drink)
          a.Name = "Maaza"
          a.Flavour = "Mango"
          b := a
          fmt.Println(&a)
          fmt.Println(&b)
          b.Name = "Frooti"
      
          fmt.Println(a.Name)
      
      }//This will output Frooti for a.Name, even though the addresses for a and b are different.
      
      Case 2:
      package main
      
      import (
          "fmt"
      )
      
      type Drink struct {
          Name    string
          Flavour string
      }
      
      func main() {
          a := Drink{
              Name:    "Maaza",
              Flavour: "Mango",
          }
      
          b := a
          fmt.Println(&a)
          fmt.Println(&b)
          b.Name = "Froti"
      
          fmt.Println(a.Name)
      
      }//This will output Maaza for a.Name. To get Frooti in this case assign b:=&a.
      

      【讨论】:

        猜你喜欢
        • 2011-11-14
        • 1970-01-01
        • 2014-06-17
        • 1970-01-01
        • 2014-10-20
        • 1970-01-01
        • 2019-05-06
        • 2017-01-11
        • 1970-01-01
        相关资源
        最近更新 更多