What you actually need to be careful to do is always return interfaces when possible because mixing interfaces and structs breaks shit.
You then also have to always return explicitly 'nil' when you mean nil. That's what GetACat messes up; if you want to return nil from a function that returns an interface, never return a struct you know to be nil, always return the literal value nil.
Why would you return an interface type? My advice is don't. Interfaces should be tightly scoped and defined by the consumer not provided by your package.
I think it's the other way around. In your package you define an interface and a struct/implementation. The contract to the user is the interface, the struct is merely an implementation detail and ideally shouldn't be public anyway so that are are free to change it.
Then you provide functions like NewCat(...) which provide instances of the interface, and which always returns either a valid implementation (non-nil type,non-nil impl tuple) or nil. The user can then directly use this like var cat Cat = NewTabby().
If you instead would return a struct pointer and the user does var cat Cat = NewTabby() you would actually triggered exactly this error. Instead he would need to check what the function returns before assigning it to an interface.
The issue you describe is not something you should design around. I have written/reviewed hundreds of thousands of lines of Go on projects large and small and have never encountered this problem. However, in practice there are very good reasons not to use interfaces as you suggest.
If you make an interface the contract with the user you will find it is now very hard to change. Everyone who had once implemented it no longer does. If I return a struct and consumers use tightly-focused interfaces for only the methods they depend on, I can continue to add methods or modify the struct as I see fit.
Think of all the engineers who will create special versions of your interface for testing. You add a new method and every single one of those needs to be updated, even if the overwhelming majority have no interest at all in the method you've added.
It's not clear which kind of nil interface you mean. :)
In Go, interface variables are a pair of values: a pointer to the concrete value stored in the variable, and a pointer to the type of that concrete value (i.e. the actual struct).
So there are essentially three kinds of nil in Go: a raw nil pointer, an interface variable with both nil value and type pointers, and an interface variable with a nil value pointer, but a non-nil type pointer.
One way that the two "interface nils" differ is that, to follow the article's example, if you have a Cat variable containing a nil *Tabby, you can invoke Meow on it, and it'll print meow. This works because Tabby's Meow doesn't try to dereference its pointer-to-Tabby. However, if you have a Cat variable that's completely empty, invoking Meow on it will fail.
What is the conceptual difference between a raw nil pointer, e.g. var t *Tabby = nil, and an interface with nil value and non-nil type? The raw pointer also has nil value and non-nil type.
The difference is that on a nil-interface you can't call a method, it will panic. On a non-nil interface it will always call the method, wether a nil-pointer is stored as the receiver or not. It a nil pointer is stored it will call the method will it, and the method may still do something useful.
It can be theoretically be used to implement some interfaces without any backing object at all (singletons, pure functions, ...), which is a difference to most other programming languages.
Sorry - the question is not immediatly understandable. If you mean how 'var t *Tabby = nil' is different from the interface representation: For this one no type information is stored at runtime. It's only a single pointer. Whereas an interface at runtime is always represented by 2 fields, a pointer and a type field.
I'll give it a shot. I'll assume you know what an interface and struct are in go.
Conceptually, an interface in Go can be thought of as two things: a concrete type, and a pointer to the implementing struct of that type.
For example, if you have `var err error = &os.PathError{}`, then the `err` variable is of type `error interface`. That `error interface` simply stores `{type = os.pathError, value = &os.PathError{}}`.
The need for the interface to have the value and the type is obvious if you consider that interfaces may have methods called upon them (so they must have an implementation), but may also be used in type assertions / switches (so they must know their underlying type).
Go, however, insists that each type has a zero value so that it may be instantiated simply, and interfaces are no different. A user may type `var err error` and create a "zero-value" interface. What should that logically be? Well, it absolutely has no way to have an underlying concrete struct since go does not provide a way to specify a default implementation for an interface, and the type is unknown too.. so it makes sense that it takes the form `{type = nil, value = nil}`.
That's a nil interface.
A nil interface is useful in many cases. One common one is to indicate the lack of a return value, such as an error. `if err := f(); err != nil` is a common pattern, and takes advantage of the existence of a nil interface, since the function must have returned one (via something like `func f() error { return nil }`).
It's also useful to have a nil interface when instantiating something sometimes. For example:
var x myInterface
// x must be *something* here
if condition1 { x = func1() }
else { x = func2() }
It's mostly useful for consistency with other parts of the language in that things have zero values.
I think the only alternative would be for an interface specification to include a "default implementation" to be used as its zero value, but that would not work if a package defines an interface of what it takes in (it would just define a default zero of a sentinel 'zero' value to error on), nor for the `interface{}` shenanigans.
Hopefully that helped, but if it didn't please ask a more specific question.
> In your hypothetical example in Go you would pick one of the set values (e.g. "1") as a "zero value".
> The alternative of not having a "zero value" is to have variables with undefined values, and we know from C/C++ that it's extremely bad idea.
Selecting a "zero value" that also happens to have actual meaning is insane.
The real alternative to not having a zero value is to require all variables to be initialized with some value. If you can't, then the variable should be an optional type wrapping the type you want. Pointers/references have something similar (you can have a valid pointer, or you can have null), but optional types are generally applicable to any type, and pulling a value out of an Option generally requires you to check for the null-equivalent or explicitly say "I know what I'm doing, assume it contains something" (unlike null pointers/references, which you can blindly dereference).
Here's the even more subtle version of that bug: https://play.golang.org/p/IVQ9MwyDGP
What you actually need to be careful to do is always return interfaces when possible because mixing interfaces and structs breaks shit.
You then also have to always return explicitly 'nil' when you mean nil. That's what GetACat messes up; if you want to return nil from a function that returns an interface, never return a struct you know to be nil, always return the literal value nil.