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.
keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
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.
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
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.
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
make
?
make
doesn't seem to return the address. I believe you can't do it in one step.
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.
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.
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
Success story sharing
json.Marshal()
will returnnull
forvar myslice []int
and[]
for initialized slicemyslice := []int{}
reflect.DeepEqual
makes a distinction between nil slices and non-nil slices:a := []int{}
,var b []int
,reflect.DeepEqual(a, b) // returns false