445

To declare an empty slice, with a non-fixed size, is it better to do:

mySlice1 := make([]int, 0) 

or:

mySlice2 := []int{} 

Just wondering which one is the correct way.

2
  • 3
    You say "non-fixed size", but slices are never have a fixed size. Unless you mean with zero capacity. Note, if you have an idea/guess/hint of what capacity you might need then using the three argument version is good. E.g. to build a slice of map keys: keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) } Commented Mar 20, 2015 at 18:06
  • 1
    Possible duplicate of Declare slice or make slice? Commented Nov 21, 2015 at 0:08

6 Answers 6

494

The two alternative you gave are semantically identical, but using make([]int, 0) will result in an internal call to runtime.makeslice (Go 1.16).

You also have the option to leave it with a nil value:

var myslice []int 

As written in the Golang.org blog:

a nil slice is functionally equivalent to a zero-length slice, even though it points to nothing. It has length zero and can be appended to, with allocation.

A nil slice will however json.Marshal() into "null" whereas an empty slice will marshal into "[]", as pointed out by @farwayer.

None of the above options will cause any allocation, as pointed out by @ArmanOrdookhani.

Sign up to request clarification or add additional context in comments.

8 Comments

Also mention on wiki github.com/golang/go/wiki/…
Be care: json.Marshal() will return null for var myslice []int and [] for initialized slice myslice := []int{}
Also be careful: reflect.DeepEqual makes a distinction between nil slices and non-nil slices: a := []int{}, var b []int, reflect.DeepEqual(a, b) // returns false
Why you think it would do an allocation? Cap is zero so nothing is allocated. All pointers to zero length things point to the same location in memory: play.golang.org/p/MPOKKl_sYvw
@КонстантинВан As of Go 1.16, they don't produce identical code, as you can see here. Using make calls runtime.makeslice, even for a zero-length slice, while the empty slice literal directly uses runtime.zerobase. Meaning, the literal is slightly faster in Go 1.16.
|
135

They are equivalent. See this code:

mySlice1 := make([]int, 0) mySlice2 := []int{} fmt.Println("mySlice1", cap(mySlice1)) fmt.Println("mySlice2", cap(mySlice2)) 

Output:

mySlice1 0 mySlice2 0 

Both slices have 0 capacity which implies both slices have 0 length (cannot be greater than the capacity) which implies both slices have no elements. This means the 2 slices are identical in every aspect.

See similar questions:

What is the point of having nil slice and empty slice in golang?

nil slices vs non-nil slices vs empty slices in Go language

Comments

72

As an addition to @ANisus' answer...

below is some information from the "Go in action" book, which I think is worth mentioning:

Difference between nil & empty slices

If we think of a slice like this:

[pointer] [length] [capacity] 

then:

nil slice: [nil][0][0] empty slice: [addr][0][0] // points to an address 

nil slice

They’re useful when you want to represent a slice that doesn’t exist, such as when an exception occurs in a function that returns a slice.

// Create a nil slice of integers. var slice []int 

empty slice

Empty slices are useful when you want to represent an empty collection, such as when a database query returns zero results.

// Use make to create an empty slice of integers. slice := make([]int, 0) // Use a slice literal to create an empty slice of integers. slice := []int{} 

Regardless of whether you’re using a nil slice or an empty slice, the built-in functions append, len, and cap work the same.


Go playground example:

package main import ( "fmt" ) func main() { var nil_slice []int var empty_slice = []int{} fmt.Println(nil_slice == nil, len(nil_slice), cap(nil_slice)) fmt.Println(empty_slice == nil, len(empty_slice), cap(empty_slice)) } 

prints:

true 0 0 false 0 0 

2 Comments

Can we get the address of empty slice in one step using make?
If we take a look at the function signature, make doesn't seem to return the address. I believe you can't do it in one step.
19

Empty slice and nil slice are initialized differently in Go:

var nilSlice []int emptySlice1 := make([]int, 0) emptySlice2 := []int{} fmt.Println(nilSlice == nil) // true fmt.Println(emptySlice1 == nil) // false fmt.Println(emptySlice2 == nil) // false 

As for all three slices, len and cap are 0.

2 Comments

make([]int, 0) is the best because Jetbrains GoLand does not complain about it being "unnecessary" as it does in the case of []int{}. This is useful in writing unit tests.
I don't think we should decide best practices based on what IDE developers' opinions.
2

In addition to @ANisus' answer

When using the official Go MongoDb Driver, a nil slice will also marshal into "null" whereas an empty slice will marshal into "[]".

When using using the community supported MGO driver, both nil and empty slices will be marshalled into "[]".

Reference: https://jira.mongodb.org/browse/GODRIVER-971

Comments

-1

This is the shortest way to initialize empty slice.

list := []int{} 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.