var x int = 5
var i interface{} = &x
*(i.(*string)) = "boom" if (bad_thing)
return ERR_BAD_THING;
... code here to turn off controlled device ...
From my understanding from prior HN discussions, panic is paired with recover; it's a kind of typeless non-local jump and unwind mechanism which can be intercepted. If the device must be turned off, then any panics must be intercepted and code must be executed to put the device in that state.I said "it's unsafe", not "it's not safer than void*".
> (i.e. exit cleanly without corrupting memory).
This makes no sense. If it exits, who cares if the memory of the process is corrupted?
Also, this is the point: it exits instead of the compiler telling you this code will crash before you ship it.
That's the point of static type safety (which Go doesn't provide in this case): it lets you ship code that is provably incorrect and that will not work once deployed (it will exit, like you say).
This is why I said "it's unsafe".
People care when memory is corrupted without the process exiting. It is usually better for a program to crash than for it to continue having corrupted its data. The former gives you x-ray machines which sometimes won't start, whilst the latter gives you x-ray machines which sometimes give the patient cancer.
I say better, not best. Best, obviously, is for as many failure modes as possible to be detected before the code is deployed. Particularly if you're programming a machine that can kill people. But in the comparison between Go's interface{} and C's void*, neither language has that option.
And it's even better to no let this program get corrupted data in the first place, which languages with a weak type system (such as Go) allow to happen whenever you use `interface{}`.
I'm sorry, but then you're simply in the wrong thread. You where replying to a interface{} vs. void comment, so that's what you should be talking about.
It's not statically type-checked, yes. That's fine too, in my opinion, but also irrelevant for a comparison with void-pointers (because they also don't provide that).
In summary, interface{} is strictly better than void-pointers. Which was exactly my point. Equating the two is intellectually dishonest.
Interesting; for some reason, I was under the impression that you could cast an `interface{}` arbitrarily, but from trying it out, you're absolutely correct. (I should definitely make sure to try these things out before confidently asserting about them...)
> interface{} is strictly better than void-pointers
No arguments here; even if for some reason they weren't type safe (which they are, much to my surprise), I'd still agree with you there.
This attitude is exactly why many choose to stay away from Go and its community. The constant denial of any problems and claims that everyone else got it wrong. I don't know where it started, most probably Pike & co; but its not very constructive.
package main
import (
"fmt"
"io"
)
type Thing struct{}
func (t *Thing) Close() error { return nil }
func main() {
var x *Thing
var y io.Closer = x
fmt.Printf("x == nil -> %#v\n", x == nil) // true
fmt.Printf("y == nil -> %#v\n", y == nil) // false
}
Here, both x and y are conceptually nil, but y cannot be compared to nil.Go is a strict language, but it's curiously lax about many things, including this. "go vet" won't even warn you that you're unintentionally wrapping nil in an interface. This goes way beyond just a trivial example like the above one, though: Any general-purpose code that has to deal with arbitrary interface{} values can't just check for nils, but need to do things like this:
func UnwrapReflectValue(v reflect.Value) interface{} {
if !v.IsValid() {
return nil
}
if v.IsNil() {
return nil
}
if v.Kind() == reflect.Ptr {
v = v.Elem()
if v.IsNil() {
return nil
}
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
return v.Interface()
}
I don't know why Go doesn't let "y == nil" return true here; boxed values are supposed to have the same high-level semantics as unboxed ones, and off the top of my head I can't think of any code where changing the current behaviour would cause breakage.I disagree with the "conceptual nilness" of y. x is a perfectly fine and usable implementation of io.Closer. It doesn't even panic. Having a nil-check (i.e. "does this interfaces contain a value?") return true seems dishonest to me.
I agree, that it was a bad choice to call both the zero-value of pointers and the zero-value of interfaces "nil". But in general, the possibility of nil-pointers being valid values and implementers of interfaces is useful. For example if you have a linked list or graph-structure.
I also asked about it on reddit and got this answer: https://www.reddit.com/r/golang/comments/6sktsr/typed_nils_i...