Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

My fave golang slice trick is the len of an empty slice is 0, but the slice itself is == to nil, but the len of nil won't compile. Can't understand that one.

https://go.dev/play/p/MslCkBphl7q?v=gotip



Because nil is a special thing in Go.

nil is not a value, it's a predeclared identifier.

it represents zero value for pointers, interfaces, maps, slices, channels and function types, representing an uninitialized value

len(nil) feels like it should work if you think of nil as the same as "value of empty array"

but what should be:

  var p *Struct
  len(p) 
  ???
There's no "length of zero-valued pointer".


Because the bare value `nil` has no type. Typing it, e.g. `len([]int(nil))` works fine.


This is the most satisfying answer, but it doesn't make the implications less complex.


What implications did you have in mind?

In languages with null and type inference, `var x = null` is probably not going to infer the type you want. In languages with function overloading (which is essentially the case for Go `len`), `f(null)` is going to be a compile-time error if multiple overloads are potentially null.


the ability to cast nil as a zero length array means there's no difference between a function that returns a zero length array and a function that returns nil (assuming some casting process takes place). It could be a subtle and annoying bug to track down the difference.


nil isn't cast to an empty slice (Go doesn't have casts, except maybe the new pointer-to-array syntax if you want to count that), nil is the default value of a slice, and that value is also empty. Other empty slices may be non-nil, because they may have capacity, or have been sliced out of another buffer, etc.

Of the various legitimate issues around nil (box vs. unboxed, nil receivers, nilability of all pointers), this is the most not-actually-ever-an-issue.


Oddly the first issue I came across today was folks being confused about this. I haven't gotten to the bottom of where the code is now, but this go library was messing up len == 0 vs nility and someone forked it to fix it: https://github.com/algorithmiaio/mapstructure/pull/1 It may not be a common bug but that doesn't make it less of a pitfall.


No, this is a terrible idea and you're in for a world of pain. If you want to distinguish "not set" from "length zero" use a *[]T or ([]T, bool), not a nil vs. non-nil-empty []T. A nil slice is not any special kind of empty slice, it is just the most efficient representation of an empty slice.


> the len of an empty slice is 0, but the slice itself is == to nil

That’s not true. An empty slice is initialized: []T{} or make(T[]); it’s not equal to nil.[1] The zero value nil slice is technically not an “empty slice”. Colloquially you may call a nil slice an empty slice, but the nil-ness is still an important distinction that manifests in e.g. encoding/json.Marshal; nil marshals to null, whereas an initialized empty slice marshals to [].

If you want to test the emptiness of a slice, test the length, don’t compare it to nil.

[1] https://go.dev/play/p/IP2NIgwvaTR?v=gotip


How does it look with json.Unmarshal? Does a JSON null decode into nil or an empty slice? And a missing JSON field?


Empty slices also serialize to `null` instead of `[]` when using the default json encoder.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: