Slices, maps and strings · 3 MIN READ

make builds the header; new only allocates

Pick make or new for a slice, a map and a pointer.

The Tour's "Creating a slice with make" page and Effective Go's "Allocation with new" page are the same distinction. new(T) allocates a zero T and returns *T. That is all it does. make is only for slices, maps and channels: it allocates the backing store and returns a usable value, not a pointer to one.

new(map[string]int) is a pointer to a nil map. Writing through it panics. make(map[string]int) is a map you can write. The same trap exists for a slice: new([]int) is *[]int pointing at nil; make([]int, 0, 8) is a slice with room.

SEE THE IDEA

Allocation and initialization answer different questions

  1. 01

    Slice

    go
    make([]int, 3)

    A usable slice with three zero elements

  2. 02

    Map or channel

    go
    make(map[string]int)

    Initializes runtime storage

  3. 03

    Pointer

    go
    new(int)

    Returns a pointer to a zero int

make returns a slice, map or channel; new returns a pointer.

In practice

Pick the form that matches the value your API needs. A struct literal often expresses initialization more clearly than new. A pointer to a nil map is still a pointer to a nil map: allocating the pointer does not initialize the map it points to.

Watch out

new([]int) yields a pointer to a nil slice. It does not allocate any slice elements.

Official reference ↗

Work through the exercise

go
package main

// ReadyMap must be writable. ZeroCounter must be a pointer to 0,
// not a nil *int.
func ReadyMap() map[string]int { return nil }
func ZeroCounter() *int        { return nil }

func main() {}
Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.