On the topic of when to use error-returns vs. when to use panic: I struggled with this aspect of Go coding too and what I decided was that, in order to choose your approach to errors, you should think about how important it is that your function can be composed into an expression: x := foo(a) + bar(b) vs. c, err := foo(a) if err != nil { ... } d, err := bar(b) if err != nil { ... } x := c + d It's a trade-off. By usi…
As I understand it, it is about severity. I think "panic" and "error" are meant to handle situations where there is no obvious, correct answer, like with array indexing. A nil pointer is another gimme example. Some languages have unchecked exceptions — maybe conceptualize it somewhat like that. panics() are for disasters, for serious program errors. By contrast, a network timeout is not a disaster. It's not "normal"…
x, err := *p
Where err is nil unless p is nil. And for array indexing: x, err := a[n]
The runtime could do its bounds check and return (zero, IndexOutOfBoundsError) if the check fails, where zero is the zero-value for the type. It seems to me that these solutions are perfectly workable except for the massive code-size/verbosity explosion they would induce.In such cases, the code should effectively prove that p is not nil and n is within bounds before performing the risky operations. Maybe a good plan is to always validate input first so that you can write expression-oriented code that only fails in the case of programmer error.
A situation from my experience was a recursive transformation where an intermediate call had no good way to deal with an error except pass it along to its caller--so I used a panic within the package for that. In hindsight, I think a better solution may have been to validate the input in an earlier pass so that the recursive transformation should always succeed.
So, in cases where the program can validate inputs first, it should do so and then be free to use compositional code that panics when the validation was broken. In cases where validation cannot remove error conditions, error-returns should be used.
Reserving panic for programmer-error, as luriel recommends in his reply, seems like a good maxim. I think I'll try to use that from now on.