5 ms·
nil in Go doesn't work that way. Most types cannot be nil.
by sythe2o0 11y ago
nil in Go doesn't work that way. Most types cannot be nil.
- nostrademons 11y agoInteresting, because (reading up on this) value types can not be nil. How often does typical Go code use values vs. interfaces or pointers? It seems like the situation is pretty similar to modern C++, which also does not allow null for value or reference types (only pointers) and encourages value-based programming. Nil is still a problem there, but less of one than in, say, Java, where everything is a reference.
- sythe2o0 11y agoIn my own experience, nil basically only shows up when I've failed to initialize something (like forgetting to loop over and make each channel in an array of channels), or when returning a nil error to indicate a function succeeded. I've never run into other interfaces being nil, but I also haven't worked with reflection and have relatively little Go experience (~6 months). The code that I've written regularly uses interfaces and pointers, but I'd guess 80% works directly with values.
- lobster_johnson 11y agoBut a bunch types you do expect to work can: Slices, maps and channels. var m map[string]bool m["foo"] = 1 // Nil, panic var a []string a[0] = "x" // Nil, panic var c chan int <-c // Blocks forever This violates the principle of least surprise. Go has a nicely defined concept of "zero value" (for example, ints are 0 and strings are empty) until you get to these. The most surprising nil wart, however, is this ugly monster: package main import "log" type Foo interface { Bar() } type Baz struct{} func (b Baz) Bar() {} func main() { var a *Baz = nil var b Foo = a fmt.Print(b == nil) // Prints false! } This happens is because interfaces are indirections. They are implemented as a pointer to a struct containing a type and a pointer to the real value. The interface value can be nil, but so can the internal pointer. They are different things. I think supporting nils today is unforgivable, but the last one is just mind-boggling. There's no excuse.
- sythe2o0 11y agoI don't think using nil to represent uninitialized data is a major issue-- if it were possible to catch uninitialized but queried variables at compile-time, that could be an improvement, but we want to give the programmer control to declare and initialize variables separately. I agree the second case is a little silly.
- aninhumer 11y agoIt's perfectly possible to separate declaration and initialisation without using a null value.
- JanKanis 11y agoI don't think you're right that interfaces are implemented as a pointer to a struct. The struct is inline like any other struct, and it contains a pointer to a type and a pointer to the value, like `([*Baz], nil)` in your example. The problem is that a nil interface in Go is compiled to `(nil, nil)` which is different. That still makes this inexcusable of course.
- lobster_johnson 11y agoYou're right, it was lurking in the back of my mind that it must be on the stack entirely.