New
does not initialize the memory, it only zeros it. It returns a pointer to a newly allocated zero value.
Make
creates slices, maps, and channels only, and it returns them initialized.
What does "initialized" mean in this context? What other differences are there between new and make?
As mentioned in Making slices, maps and channels:
The built-in function make takes a type
T
, which must be a slice, map or channel type, optionally followed by a type-specific list of expressions.
It returns a value of typeT
(not*T
).
The memory is initialized as described in the section on initial values.
For instance, for Slice type
make([]T, length, capacity)
produces the same slice as allocating an array and slicing it, so these two expressions are equivalent:
make([]int, 50, 100)
new([100]int)[0:50]
So here, make creates the slice, and initialize its content depending on the zero value if the type used (here int
, so '0
')
You can see more about the need of keeping new and make separate in Go: why would I make() or new()?
Dave cheney just wrote a good article: "Go has both make and new functions, what gives ?"
Although
make
creates genericslice
,map
, andchannel
values, they are still just regular values; make does not return pointer values.If
new
was removed in favourmake
, how would you construct a pointer to an initialised value ?Using
new
to construct a pointer to aslice
,map
, orchannel
zero value works today and is consistent with the behaviour ofnew
.For the confusion they may cause,
make
andnew
are consistent;
make
only makes slices, maps, and channels,new
only returns pointers to initialised memory.
First difference is type: make(T, ...)
always returns type T
, whereas new(T, ...)
always returns type *T
. That tells you that they are very different.
new
works for all types, and dynamically allocates space for a variable of that type, initialized to the zero value of that type, and returns a pointer to it.
One way to think of it is that
result = new(T)
is always equivalent to
var temp T
result = &temp
(in other words you can do the same thing that new
does by defining a variable of the given type, not initializing it, and then taking a pointer to it.)
make
works as a kind of "constructor" for certain built-in types (slice, map, or channel).
The builtin new(T) function allocates “zeroed” storage for a new item of type T and returns its address, a value of type *T. In Go terminology, it returns a pointer to a newly allocated zero value of type T. For example, here are three different ways to create a pointer p that points to a zeroed bytes.Buffer value, each of which are equivalent:
// 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)
The make() function, on the other hand, is a special built-in function that is used to initialize slices, maps, and channels. Note that make() can only be used to initialize slices, maps, and channels, and that, unlike the new() function, make() does not return a pointer.
Slices, maps, and channels can also be initialized using a composite literal expressions, as well as with make(). Two different (yet equivalent) ways to initialize a map m which maps string keys to bool values are given below as examples:
// Using make() to initialize a map.
m := make(map[string]bool, 0)
// Using a composite literal to initialize a map.
m := map[string]bool{}
// You can also initialize maps with initial data using a composite literal,
// as shown below:
m := map[string]bool{
"java": false,
"go": true,
}