Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between new(Struct) and &Struct{} in Go?

Tags:

go

They seem to be the same:

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.
}

Update:

Hm. I just realized that there's no obvious way to initialize S.i using new. Is there a way to do that? new(S{i:1}) does not seem to work :/

like image 579
allyourcode Avatar asked Aug 24 '13 16:08

allyourcode


2 Answers

From Effective Go:

As a limiting case, if a composite literal contains no fields at all, it creates a zero value for the type. The expressions new(File) and &File{} are equivalent.

like image 107
Woot4Moo Avatar answered Oct 23 '22 07:10

Woot4Moo


Not only do they give the same resulting value, but if we allocate something both ways and look at their values...

// 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)
}

...we'll see that they are in fact allocated in consecutive memory slots. Typical output: 0x10328100 0x10328108. I'm not sure if this is an implementation detail or part of the specification, but it does demonstrate that they're both being allocated from the same pool.

Play around with the code here.

As for initializing with new, according to the language spec: The 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. Because functions in go can't be overloaded, and this isn't a variadic function, there's no way to pass in any initialization data. Instead, go will initialize it with whatever version of 0 makes sense for the type and any member fields, as appropriate.

like image 2
Ionoclast Brigham Avatar answered Oct 23 '22 09:10

Ionoclast Brigham