Question: Go provides two ways of handling errors, but I'm not sure which one to use.

Assuming I'm implementing a classic `ForEach` function which accepts a slice or a map as an argument. To check whether an iterable is passed in, I could do:

```
func ForEach(iterable interface{}, f interface{}) {
    if isNotIterable(iterable) {
        panic("Should pass in a slice or map!")
    }
}

```

or 

```
func ForEach(iterable interface{}, f interface{}) error {
    if isNotIterable(iterable) {
        return fmt.Errorf("Should pass in a slice or map!")
    }
}

```

I saw some discussions saying `panic()` should be avoided, but people also say that if program cannot recover from error, you should `panic()`.

Which one should I use? And what's the main principle for picking the right one?

Answer: 
If some mandatory requirement is not provided or not there while starting the service (eg. database connection, some service configuration which is required) then you should use panic.

There should be return error for any user response or server side error.
I think none of the previous answers are correct:

* By default, if we don't know what to do with the "error" code must panic following best programming patterns:
<https://en.wikipedia.org/wiki/Fail-fast>

Putting it more formally, our "Turing Machine" is broken and we need to come back to an "stable state" or "reset state". More info at <https://en.wikipedia.org/wiki/Reset_(computing)>

For example in web (micro)services that means returning a 40X error (panic caused by input from user) or 50X error (panic caused by something else - hardware, network, assert error, ...)

* If we know what to do with the "error", then we do not have an error in first place, but an uncomfortable return value. This is a normal execution condition and probably not an error. Normally this correspond to the happy vs non-happy path modeling.

In a summary, the err return value is mostly a wrong idea, even if the GO community has adopted it as a religion. Using error return values is just a patchy way to speed up program execution since it require fewer CPU instructions to be implemented, but most of the time, except for low-level services, it is useless and promote dirty code. (note that GO was designed to implement those low-level services as an "easy-C", but it was adopted for high-level (Level 7) application programs when an error must fail fast to avoid continuing with undefined states that can potentially cause money being lost of fatal casualties. In case of doubt, default to panic.