409

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.

eouti
  • 5,338
  • 3
  • 34
  • 42
  • 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) }` – Dave C Mar 20 '15 at 18:06
  • 1
    Possible duplicate of [Declare slice or make slice?](http://stackoverflow.com/questions/25543520/declare-slice-or-make-slice) – user Nov 21 '15 at 00:08

5 Answers5

454

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.

ANisus
  • 74,460
  • 29
  • 162
  • 158
  • 4
    Also mention on wiki https://github.com/golang/go/wiki/CodeReviewComments#declaring-empty-slices – Grzegorz Żur Mar 20 '15 at 10:50
  • 170
    Be care: `json.Marshal()` will return `null` for `var myslice []int` and `[]` for initialized slice `myslice := []int{}` – farwayer Jul 11 '17 at 23:52
  • 15
    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` – asgaines Jun 13 '18 at 15:25
  • 1
    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: https://play.golang.org/p/MPOKKl_sYvw – Arman Ordookhani Apr 21 '20 at 14:10
  • 1
    @ArmanOrdookhani You are correct. I tried it out, and I also found out that I was wrong with my assumption on identical assembly instructions. Fixed! – ANisus Apr 21 '20 at 15:42
  • 1
    “Semantically identical.” Are those identical in performance, too? Does the internal call make it slower than the one without `make(…)`? – Константин Ван Apr 28 '21 at 17:37
  • 2
    @КонстантинВан As of Go 1.16, they don't produce identical code, as you can see [here](https://godbolt.org/z/Gj7so7ETx). Using _make_ calls [`runtime.makeslice`](https://golang.org/pkg/runtime/?m=all#makeslice), even for a zero-length slice, while the empty slice literal directly uses [`runtime.zerobase`](https://golang.org/pkg/runtime/?m=all#zerobase). Meaning, the literal is slightly faster in Go 1.16. – ANisus Apr 29 '21 at 06:44
  • 1
    Is there a way to change the behavior of `json.Marshal` so that it returns `[]` for a `nil` slice? – Max Jul 08 '22 at 15:52
129

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

icza
  • 389,944
  • 63
  • 907
  • 827
66

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
tgogos
  • 23,218
  • 20
  • 96
  • 128
  • Can we get the address of empty slice in one step using `make`? – Cloud Jul 16 '18 at 12:43
  • If we take a look at the function [signature](https://golang.org/pkg/builtin/#make), `make` doesn't seem to return the address. I believe you can't do it in one step. – tgogos Jul 16 '18 at 13:06
18

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.

IanS
  • 15,771
  • 9
  • 60
  • 84
Joe.CK
  • 339
  • 3
  • 2
  • 1
    `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. – Andrzej Rehmann Dec 25 '18 at 16:29
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