4 ms·
I 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
by stouset 10y ago
I 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.)
- stouset 10y agoYou don't have to keep explaining the mechanism. I get the mechanism. But the fact that `foo == nil` can return false when foo is actually nil is indefensible. The fact that it crashes less than C does is not a defense here. Sorry.
- dilap 10y agoBut the fact that `foo == nil` can return false when foo is actually nil is indefensible. You keep saying this, but it's not true.
- stouset 10y agoOnly because go has redefined the terms. … foo = nil bar = foo // this check may or may not evaluate as true if (bar == nil) { … } Saying that `bar` here isn't actually equal to nil if it's an interface is tautological. It's not, but only because the language has defined this to be the case. Go could likewise define `1 == 2` to evaluate to true, and you could reuse the same semantic reasoning to defend it. The point being argued is that it doesn't matter that go defines this to be the case, the point being argued is that it's surprising, frustrating, and can lead to bugs. Particularly when `bar` starts off as a pointer to a struct, but later is refactored to be an interface type. Code that used to work still compiles, but now encounters a runtime nil panic.
- dilap 10y ago(See also my response to jerf, above.) In Go (as in most programming languages) it's not true that the assignment "a = b" implies that "b == foo => a == foo", if a and b are different types. For example, this C code will print "nope": float b = 3.5; int a = b; printf(a==3.5 ? "yup" : "nope\n"); So back to Go, sure, this is initially surprising, and most people get bit by it at first. Once you know about it, it's fine. In practice I haven't encountered any refactoring bugs as you describe, though it is theoretically possible. I personally don't see it as a big issue. (In retrospect, Go could've help guide intuition better by using a new keyword like "unset" or something to test for the zero-value of interfaces, instead of overloading nil.)
- dragonwriter 10y ago> In Go (as in most programming languages) it's not true that the assignment "a = b" implies that "b == foo => a == foo", if a and b are different types. While I haven't counted and compared, I suspect that in most programming languages, "a=b" being a non-error implies that either a and b are the same type and value, or that a and b are values that, if they are of different and comparable types, will compare equal. There are certainly popular languages that do it the way you describe, but I don't think most languages do.