Um contrato frequentemente usado para funções que retornam um valor de erro de um tipo de interface é que o chamador não deve saber nada sobre o estado de outros valores retornados por essa chamada sem primeiro verificar o erro.
Na maioria dos casos, os valores de erro retornados pelas funções devem ser opacos para o chamador. Ou seja, um teste no qual o erro é nulo mostra se a chamada foi bem-sucedida ou falhou, e é tudo o que você precisa fazer.

foto daqui
Um pequeno número de casos, geralmente associado a interações com o mundo externo, como atividade de rede, exige que o chamador examine a natureza do erro para decidir se deve ou não repetir a operação.
Um requisito comum para os autores de pacotes é retornar erros de tipo público conhecidos, para que o chamador possa usar a declaração de tipo e examiná-los em detalhes. Eu acredito que esta prática leva a uma série de resultados indesejáveis:
- Tipos abertos de erros aumentam a "área de contato" com a API do pacote.
- Novas implementações devem retornar apenas os tipos especificados na declaração da interface, mesmo que não se encaixem bem.
- O tipo de erro, depois de adicionado ao código, não pode ser alterado ou preterido sem quebrar a compatibilidade, tornando a API frágil.
Confirme o comportamento esperado, não o tipo de erro
Não afirme que o valor do erro é um tipo específico, mas afirme que o valor implementa um comportamento específico.
Essa frase é consistente com a natureza das interfaces implícitas Go e não é um [subtipo] da natureza das linguagens baseadas em herança. Considere este exemplo:
func isTimeout(err error) bool { type timeout interface { Timeout() bool } te, ok := err.(timeout) return ok && te.Timeout() }
O chamador pode usar isTimeout () para determinar se o erro atingiu o tempo limite implementando a interface de tempo limite e, em seguida, confirmar se o erro foi atingido pelo tempo limite - tudo sem saber nada sobre o tipo ou origem valores de erro.
Esse método possibilita agrupar erros, como regra, com bibliotecas que adicionam explicações ao caminho do erro; desde que os tipos de erro agrupados também implementem as interfaces de erro que eles agrupam.
Isso pode parecer um problema insolúvel, mas, na prática, existem alguns métodos de interface geralmente aceitos; portanto, Timeout () bool e Temporary () bool abrangem uma ampla variedade de casos de uso.
Em conclusão
Confirme o comportamento esperado, não o tipo de erro
Para autores de pacotes
Se o seu pacote gerar erros de natureza temporária, certifique-se de retornar os tipos de erro que implementam os métodos de interface apropriados. Se você agrupar os valores de erro de saída, verifique se os wrappers suportam as interfaces com as quais o valor original do erro é implementado.
Para usuários do pacote
Se você precisar verificar se há um erro, use as interfaces para confirmar o comportamento esperado, não o tipo de erro. Não pergunte aos autores do pacote sobre os tipos de erro em aberto; peça que eles alinhem seus tipos com interfaces comuns, especificando os métodos Timeout () ou Temporary (), conforme apropriado.
Sobre o autor
O autor deste artigo, Dave Cheney , é o autor de muitos pacotes populares do Go, por exemplo, https://github.com/pkg/errors e https://github.com/davecheney/httpstat .
Do tradutor
Embora o artigo original esteja datado até o final de 2014, parece-me que ele não perdeu sua relevância. A abordagem descrita é encontrada em alguns pacotes, enquanto o restante usa a abordagem usual para erros.
Edições no texto para aumentar a clareza do material são bem-vindas!