3 ms·
> I really don't miss having invisible control flow for expected conditions blowing up my programs with long stack traces. You mean outside of accidentally run
by stouset 10y ago
> I really don't miss having invisible control flow for expected conditions blowing up my programs with long stack traces.
You mean outside of accidentally running into a nil, and having your program spontaneously abort?
Even worse, reliably testing for nil (`if (foo == nil)`) doesn't even save you because go's nils are typed. So `foo == nil` can actually return false even when foo is nil. Utter madness.
- Vendan 10y agoGo's nils aren't typed, it's just that an interface value can have a type and point at nil. Also, I've never run into this "problem" in all my time of using Go...
- deleted 10y ago[deleted]
- dilap 10y agoRunning into a nil would be an "unexpected condition". In that case, an exception (panic, in Go lingo) is reasonable. It is true that Go doesn't do as much as other languages to avoid nils. It's a small, unambitious language in some ways. (Like, it adds more typing than Python, not as much as rust or swift.) foo == nil will always tell you the truth. The edge case that trips people up at first that I think you're thinking of is that storing a nil-pointer into an interface will not give you a nil interface: package main import "fmt" type Foo struct{} func (f *Foo) Do() { fmt.Println("do the foo", f) } type Doer interface { Do() } func main() { var foo *Foo = nil fmt.Println(foo == nil) // true var doer Doer = foo fmt.Println(doer == nil) // false, because doer is (nil,Foo) doer.Do() // prints "do the foo <nil>" } https://play.golang.org/p/Ul9cX34qfF https://play.golang.org/p/Ul9cX34qfF That's because an interface is a (pointer,type) pair, so even if the pointer is nil, the type being non-nil will make the pair non-nil.
- stouset 10y agoI understand how and why this works. But the fact that you can write some form of var foo *Foo = nil var bar Bar = foo foo == nil # true bar == nil # false is, to be completely honest, completely ridiculous. It means you can perform a sanity check for nil values and still accidentally operate on a nil value. Null references have been referred to by Tony Hoare as his billion-dollar mistake. We should not be reintroducing mistakes of this level of magnitude, and worse, compounding on them, in new languages invented with fifty years of hindsight.
- jerf 10y agoIt's because nil values aren't invalid the way they are in C. You can having a nil Object pointer but still call methods on it: func (o *Object) DoSomething() { if o == nil { fmt.Println("Nil implementation") } fmt.Println("Something with the members here") } Whether or not this is a good idea would be a different discussion, but typed nil struct pointers don't automatically crash the way they do in C. Therefore, it is perfectly valid to have some interface implemented by what is a nil pointer to some object type. I've even used this a few times. nil only crashes when you try to write into a nil map and a few other operations. Even some operations you'd expect to crash are implemented in a way that they will not. For instance, you can append to a nil slice, and a new slice and underlying array will be allocated for you rather than crashing. Go does not by any means solve the "billion-dollar mistake", and I'd still like to be able to put "non-nillable" on things, but it is less affected by it than C. (Which is damning with faint praise, certainly.)