Go has two allocation primitives, the built-in functions new and make.

new

The built-in new(T) function returns a pointer to a newly allocated zero value of type T. For example, there’re 3 different ways to create a pointer p that points to a zeroed bytes.Buffer value, each of which are equivalent:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Allocate enough memory to store a bytes.Buffer value
// and return a pointer to the value's address.
var buf bytes.Buffer
p := &buf

// Use a composite literal to perform allocation and
// return a pointer to the value's address.
p := &bytes.Buffer{}

// Use the new function to perform allocation, which will
// return a pointer to the value's address.
p := new(bytes.Buffer)

Some document in go source libray.

1
2
3
4
5
// https://golang.org/src/builtin/builtin.go?s=7789:7809#L184
// 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.
func new(Type) *Type

make

The built-in make(T, args) applies only to maps, slices and channels, it returns an initialized(not zeroed) value of type T(not *T).

Some document in go source libray.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// https://golang.org/src/builtin/builtin.go?s=7566:7609#L179
// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
//	Slice: The size specifies the length. The capacity of the slice is
//	equal to its length. A second integer argument may be provided to
//	specify a different capacity; it must be no smaller than the
//	length. For example, make([]int, 0, 10) allocates an underlying array
//	of size 10 and returns a slice of length 0 and capacity 10 that is
//	backed by this underlying array.
//	Map: An empty map is allocated with enough space to hold the
//	specified number of elements. The size may be omitted, in which case
//	a small starting size is allocated.
//	Channel: The channel's buffer is initialized with the specified
//	buffer capacity. If zero, or the size is omitted, the channel is
//	unbuffered.
func make(t Type, size ...IntegerType) Type

Of course we can new a slice, map or channel, but it rarely has any sense.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
s := new([]string)
fmt.Println(len(*s))  // 0
fmt.Println(*s == nil) // true

m := new(map[string]int)
fmt.Println(m == nil) // false
fmt.Println(*m == nil) // true

c := new(chan int)
fmt.Println(c == nil) // false
fmt.Println(*c == nil) // true

Conclusion

In short, new(T) returns address of zeroed allocation of type T, make() only works for slice, map and channel and returns value instead of pointer.

References