Home > database >  Difference in Go between allocating memory by new(Type) and &Type{}
Difference in Go between allocating memory by new(Type) and &Type{}

Time:11-01

Consider the following example:

type House struct{}

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

Output: *main.House | *main.House

Both assignments produce a pointer to type House (from package main).

From the go docu of 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.

Is memory allocation in both assignments technically the same? Is there a best practice?

CodePudding user response:

Is memory allocation in both assignments technically the same?

I'm not going to talk about implementation details, since those may or may not change.

From the point of view of the language specifications, there is a difference.

Allocating with new(T) follows the rules of allocation (my own note in [italics]):

The built-in function new takes a type T, allocates storage for a variable of that type at run time, and returns a value of type *T pointing to it. The variable is initialized as described in the section on initial values. [its zero value]

Allocating with a composite literal as &T{} follows the rules of composite literals and addressing:

Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated.

Taking the address of a composite literal generates a pointer to a unique variable initialized with the literal's value.

So both new(T) and &T{} allocate storage and yield values of type *T. However:

  • new(T) accepts any type, including predeclared identifiers as int and bool, which may come in handy if you just need to initialize such vars with a one-liner:
n := new(int) // n is type *int and points to 0
b := new(bool) // b is type *bool and points to false
  • new "does not initialize that memory" (source)1. The memory location will have the type's zero value.
  • composite literals can be used only for structs, arrays, slices and maps
  • composite literals can construct non-zero values by explicitly initializing struct fields or array/slice/map items

Bottom line: as Effective Go points out (same paragraph as above):

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


[1]: there's a small inconsistency between wording in the specs and Effective Go. The take-away is that with new you can only yield a zero-value, whereas a composite literal allows you to construct non-zero values. And obviously the specs are the source of truth.

  •  Tags:  
  • go
  • Related