Making slices, maps and channels
The built-in function
make
takes a typeT
, optionally followed by a type-specific list of expressions. The core type ofT
must be a slice, map or channel. It returns a value of typeT
(not*T
). The memory is initialized as described in the section on initial values.Call Core type Result make(T, n) slice slice of type T with length n and capacity n make(T, n, m) slice slice of type T with length n and capacity m make(T) map map of type T make(T, n) map map of type T with initial space for approximately n elements make(T) channel unbuffered channel of type T make(T, n) channel buffered channel of type T, buffer size n
The only time you absolutely need to use make
is when creating channels. For slices and maps, there are alternatives, though there are still times when you’ll want to use make
for convenience, or even performance.
These bits of code are equivalent:
x := make([]int, 0)
y := make(map[string]string)
and
x := []int{}
y := map[string]string{}
So why bother with make
for these types of variables?
Mainly, for pre-allocation.
Recall our recent discussion on efficiently appending to slices. If you know that a slice will need to hold a certain number of elements, you can pre-allocate that number of elements at the time you create the slice, rather than relying on append
growing the slice, and exercising the garbage collector unduely.
x := make([]int, 0, 100) // x can grow to 100 elements, without another allocation
If you know how many elements a map is likely to contain, you can also pre-allocate enough space when creating a map. Although as we see below, the exact behavior here is much less strictly defined than it is for slices.
y := make(map[string]string, 50)
Each of the size arguments
n
andm
must be of integer type, have a type set containing only integer types, or be an untyped constant. A constant size argument must be non-negative and representable by a value of typeint
; if it is an untyped constant it is given typeint
. If bothn
andm
are provided and are constant, thenn
must be no larger thanm
. For slices and channels, ifn
is negative or larger thanm
at run time, a run-time panic occurs.s := make([]int, 10, 100) // slice with len(s) == 10, cap(s) == 100 s := make([]int, 1e3) // slice with len(s) == cap(s) == 1000 s := make([]int, 1<<63) // illegal: len(s) is not representable by a value of type int s := make([]int, 10, 0) // illegal: len(s) > cap(s) c := make(chan int, 10) // channel with a buffer size of 10 m := make(map[string]int, 100) // map with initial space for approximately 100 elements
Calling make with a map type and size hint
n
will create a map with initial space to holdn
map elements. The precise behavior is implementation-dependent.
Quotes from The Go Programming Language Specification Language version go1.23 (June 13, 2024)