Have you actually had problems with nil pointers in Go? I've written it for years without facing it so perhaps you're doing something radically different if you managed to come across it.
My experience is the same. Go mitigates pointer problems very well by having zero values and explicitly separating error returns.
If anyone complains about having nil in Go, I usually assume they're either forced to work a really bad codebase or lack experience in Go.
I've worked on a Go codebase for ~2 years, and I'm pretty sure the only nil pointer dereference I've seen was due to a concurrency bug, where an object cache (implemented as an array, not sync.Pool) was not locked properly.
The problem with having nil is when you expect a value to be either a valid pointer or nil to indicate an error, and you forget to check for an error. In Go, in my experience, explicit error checking and multiple return values makes that a non-problem, however ugly some people consider it to be. If I see error assignments to _, that makes me raise my eyebrows.
How do zero values help here? Zero values would seem to me to make nil pointer panics easier to run across, because it means the language can silently insert nil into your data structures or assign nil to your variables without any syntactic indication.
> The problem with having nil is when you expect a value to be either a valid pointer or nil to indicate an error, and you forget to check for an error.
That's not the problem with null pointers. Null is used all over the place for non-error conditions. The problem is when an object legitimately might or might not be present, but the type doesn't encode that fact, so some code mistakenly assumes that the object is always present when it isn't.
> The problem is when an object legitimately might or might not be present, but the type doesn't encode that fact, so some code mistakenly assumes that the object is always present when it isn't.
Yes reworded slightly, types encode value invariants, nullable types can't encode one of their invariants.
My complain with nil in Go is that there are different kinds of it as a nil pointer to a struct is not equal to a nil pointer of the interface it implements and code like https://play.golang.org/p/NwKvIztXwP prints false.
This is the reason for the rule of always returning error type in Go, not a pointer to detailed struct error. That leads to an ugly code when a check for non-nil err is followed by a cast.