RSVP here for our first hackathon! Free prizes, the kickoff is 8 AM PST Jan 17th

Should You Return Empty or Nil Slices in Go?

A learning path to your next coding job

  1. Join the Qvault community and share your career goals
  2. We'll help you find the knowledge gaps holding you back
  3. Complete recommended courses and projects
  4. Find your next opportunity with a newly polished resume

Our courses include but are not limited to

  • Golang, Python, JavaScript
  • Algorithms, data structures, cryptography
  • Graphics and functional programming

In Go, we often need to return zero values. Idiomatic Go encourages the use of guard clauses, and guard clauses necessitate the need to return early. When returning early with an error, by convention all other return values should be zero values. The confusion arises with data types like maps and slices. Should maps and slices be returned as a simple nil value, or should an empty but instantiated value be returned?

For example, should we use this syntax?

func getItems(url string) ([]string, error) { data, err := makeRequest(url) if err != nil { return nil, err } items, err := unpack(data) if err != nil { return nil, err } return data, nil }
Code language: Go (go)

Or perhaps this syntax?

func getItems(url string) ([]string, error) { data, err := makeRequest(url) if err != nil { return []string{}, err } items, err := unpack(data) if err != nil { return []string{}, err } return data, nil }
Code language: Go (go)

The Differences

I ran a quick bit of code to show some of the differences between nil and empty slices:

package main import ( "encoding/json" "fmt" ) func main() { var nilSlice []string fmt.Println(nilSlice) // Output: [] fmt.Println(len(nilSlice), cap(nilSlice)) // Output: 0 0 fmt.Println(nilSlice == nil) // Output: true dat, _ := json.Marshal(nilSlice) fmt.Println(string(dat)) // Output: null emptySlice := []string{} fmt.Println(emptySlice) // Output: [] fmt.Println(len(emptySlice), cap(emptySlice)) // Output: 0 0 fmt.Println(emptySlice == nil) // Output: false dat, _ = json.Marshal(emptySlice) fmt.Println(string(dat)) // Output: [] }
Code language: Go (go)

As you can see there are some similarities between nil and empty slices:

  • Both have zero length and cap
  • Both print []
  • Both can be used the same way in range loops and append functions (not shown here)

They differ in the following ways:

  • Only a nil slice will succeed a nil check
  • When encoded as JSON using the standard library, the nil slice becomes null and the empty slice becomes []

Which Should I Do?

Generally speaking, prefer nil.

According to the Go wiki, nil is the preferred style. When we just need to return an empty slice nil will work great in practically all cases. It’s also easier to type nil than []string{} or make([]string, 0) and typically gets syntax highlighted which makes it easier to read.

Related Content

Trying to find your next programming job?

If you are a self-taught developer having trouble finding your first programming job, we've got your back! We have the learning resources and tight-knit dev community that you need to land the coding job you've been looking for. To get started, create a free account and join our Discord community.

Have questions or feedback?

If we've made a mistake in the article, please let us know so we can get it corrected!

Leave a Comment