Técnicas de tratamento de erros Go [fechado]
Quer melhorar esta questão? Atualize a pergunta para que ela possa ser respondida com fatos e citações editando este post .
Estou apenas começando com Go. Meu código está começando a ter muito disso:
Existem boas expressões idiomáticas / estratégias / melhores práticas para verificar e lidar com erros no Go?
EDIT para esclarecer: não estou reclamando ou sugerindo que a equipe Go venha com algo melhor. Estou perguntando se estou fazendo certo ou se perdi alguma técnica que a comunidade criou. Obrigado a todos.
— gmoore
Não, não há realmente. Esse é um tópico frequentemente discutido e sensato. Houve muitas propostas de evolução também. A resposta da equipe parece ser que isso não deve ser um problema em um código bem escrito.
Relacionado: stackoverflow.com/questions/15397419/…
Observe que esta questão relacionada não é realmente a mesma. As respostas são muito específicas.
Também há uma razão para esse aborrecimento: torna mais difícil escrever um programa rapidamente, mas também torna mais difícil criar bugs simplesmente relançando os erros.
Você pode encontrar Andrew Gerrand e Brad Fitzpatrick escrevendo o início de um cliente HTTP / 2 em Go de maneira mais ou menos semelhante youtube.com/watch?v=yG-UaBJXZ80
— Supreet Sethi
Seu código é idiomático e, em minha opinião, é a melhor prática disponível. Alguns discordariam com certeza, mas eu diria que esse é o estilo visto em todas as bibliotecas padrão em Golang . Em outras palavras, os autores de Go escrevem o tratamento de erros dessa maneira.
"Os autores do Go escrevem o tratamento de erros dessa maneira." Parece bom para mim.
"Alguns discordariam com certeza" : não tenho certeza se alguém diria que não é a melhor prática disponível hoje. Alguns pedem sintaxe sugar ou outras mudanças, mas hoje eu não acho que nenhum programador sério iria verificar os erros de outra forma.
@dystroy: OK, alguns dizem " é sux ", outros chamam de "erros são tratados em valores de retorno. Estilo dos anos 70". e assim por diante ;-)
@jnml Manipular erros dessa forma é uma questão de design de linguagem, que é um tópico altamente controverso. Felizmente, existem dezenas de idiomas para escolher.
O que me mata é como o mesmo padrão é usado para cada chamada de função. Isso torna o código um tanto barulhento em alguns lugares e é apenas gritar por açúcar sintático para simplificar o código sem perder nenhuma informação, que é essencialmente a definição de concisão (que acredito ser um atributo superior do que a verbosidade, mas isso é discutivelmente controverso ponto). O princípio é bom, mas a sintaxe deixa muito a desejar IMHO. No entanto reclamar é proibido, então vou beber meu kool-aid agora ;-)
Seis meses depois que essa pergunta foi feita, Rob Pike escreveu uma postagem no blog intitulada Erros são valores .
Lá ele argumenta que você não precisa programar da maneira apresentada pelo OP e menciona vários lugares na biblioteca padrão onde eles usam um padrão diferente.
É claro que uma instrução comum envolvendo um valor de erro é testar se ele é nulo, mas há inúmeras outras coisas que se pode fazer com um valor de erro, e a aplicação de algumas dessas outras coisas pode tornar seu programa melhor, eliminando muito do boilerplate que surge se cada erro é verificado com uma instrução if rotineira.
Use a linguagem para simplificar o tratamento de erros.
Mas lembre-se: faça o que fizer, verifique sempre os seus erros!
— Michael Deardeuff
Obrigado! Vou verificar isso.
O artigo é incrível, basicamente apresenta um objeto que pode estar em estado de falha e, se estiver, simplesmente ignorará tudo o que você fizer com ele e permanecerá em estado de falha. Para mim parece quase-mônada.
— Waterlink
@Waterlink Sua declaração não tem sentido. Tudo que tem um estado é quase-mônada, se você olhar um pouco mais estreito. Compará-lo com en.wikipedia.org/wiki/Null_Object_pattern é mais útil, eu acho.
@ user7610, Obrigado por um feedback. Eu só posso concordar.
— Waterlink de
Pike: "Mas lembre-se: faça o que fizer, verifique sempre os seus erros!" - isso é tão anos 80. Erros podem ocorrer em qualquer lugar, parar de sobrecarregar os programadores e adotar exceções para o bem de Pete.
— Slawomir,
Eu concordaria com a resposta do jnml de que ambos são códigos idiomáticos e adicionaria o seguinte:
Seu primeiro exemplo:
é mais idiomático ao lidar com mais de um valor de retorno. por exemplo:
Seu segundo exemplo é uma boa abreviatura ao lidar apenas com o errvalor. Isso se aplica se a função retornar apenas um errorou se você ignorar deliberadamente os valores retornados diferentes de error. Por exemplo, às vezes é usado com as funções Readere Writerque retornam um intdo número de bytes gravados (às vezes informações desnecessárias) e um error:
A segunda forma é conhecida como o uso de uma instrução de inicialização if .
Portanto, com relação às melhores práticas, até onde eu sei (exceto pelo uso do pacote "errors" para criar novos erros quando você precisar deles), você cobriu praticamente tudo o que precisa para saber sobre os erros no Go!
EDIT: Se você descobrir que realmente não pode viver sem exceções, você pode imitá-los com defer, panic&recover .
Fiz uma biblioteca para agilizar o tratamento de erros e canalizar uma fila de funções Go.
Você pode encontrá-lo aqui: https://github.com/go-on/queue
Possui uma variante sintática compacta e detalhada. Aqui está um exemplo para a sintaxe curta:
Esteja ciente de que há uma pequena sobrecarga de desempenho, uma vez que faz uso de reflexão.
Além disso, este não é um código go idiomático, então você vai querer usá-lo em seus próprios projetos ou se sua equipe concordar em usá-lo.
— metakeule
Só porque você pode fazer isso, não significa que seja uma boa ideia. Parece o padrão da Cadeia de Responsabilidade , mas talvez seja mais difícil de ler (opinião). Eu sugeriria que não é um "Go idiomático". Interessante, entretanto.
Uma "estratégia" para lidar com erros em golang e em outras linguagens é propagar erros continuamente pela pilha de chamadas até que você esteja alto o suficiente na pilha de chamadas para lidar com esse erro. Se você tentou lidar com esse erro muito cedo, provavelmente acabará repetindo o código. Se você lidar com isso tarde demais, você quebrará algo em seu código. Golang torna esse processo muito fácil, pois torna muito claro se você está lidando com um erro em um determinado local ou propagando-o.
Se você for ignorar o erro, um simples _ revelará esse fato muito claramente. Se você estiver lidando com isso, então exatamente qual caso do erro você está lidando é claro, pois você verificará na instrução if.
Como as pessoas disseram acima, um erro é na verdade apenas um valor normal. Isso o trata como tal.
— himanshu ojha
Os deuses Go publicaram um "projeto de projeto" para tratamento de erros no Go 2. O objetivo é mudar o idioma dos erros:
Visão geral e design
Eles querem feedback dos usuários!
Wiki de feedback
Resumidamente, parece:
ATUALIZAÇÃO: o projeto de rascunho recebeu muitas críticas, então eu elaborei Requisitos a serem considerados para o tratamento de erros do Go 2 com um menu de possibilidades para uma eventual solução.
A maioria na indústria segue as regras padrão mencionadas na documentação do golang Tratamento de erros e Go . E também ajuda na geração de documentos para o projeto.
— pschilakanti
Esta é essencialmente uma resposta apenas com link. Eu sugeriria que você adicionasse algum conteúdo à resposta para que, se o link se tornar inválido, sua resposta ainda seja útil.
— Neo de
Abaixo está minha opinião sobre como reduzir o tratamento de erros no Go, um exemplo é para obter parâmetros de URL HTTP:
(Padrão de design derivado de https://blog.golang.org/errors-are-values )
chamá-lo para vários parâmetros possíveis seria o seguinte:
Isso não é uma solução mágica; a desvantagem é que, se você teve vários erros, só poderá obter o último erro.
Mas, neste caso, é relativamente repetitivo e de baixo risco, portanto, posso obter apenas o último erro possível.
Você pode limpar seu código de tratamento de erros para erros semelhantes (uma vez que os erros são valores, você deve ter cuidado aqui) e escrever uma função que você chama com o erro passado para tratar o erro. Você não terá que escrever "if err! = Nil {}" toda vez. Novamente, isso só resultará na limpeza do código, mas não acho que seja a maneira idiomática de fazer as coisas.
Novamente, só porque você pode , não significa que você deve .
— 20kLeagues
goerr permite lidar com erros com funções
— Anlhord Smithson
Ick. Complicar / ocultar a lógica de tratamento de erros como essa não é uma boa ideia IMO. O código resultante (que precisa de pré-processamento de origem por goerr) é mais difícil de ler / raciocinar sobre o código idiomático Go.
Se você quer um controle preciso dos erros, essa pode não ser a solução, mas para mim, na maioria das vezes, qualquer erro é um obstáculo.
Então, eu uso funções.
Essas mensagens devem ir para em stderrvez de stdout, então use apenas log.Fatal(err)ou log.Fatalln("some message:", err). Uma vez que quase nada além de maintomar essa decisão de encerrar todo o programa (ou seja, retornar erros de funções / métodos, não abortar), no caso raro, isso é o que você deseja fazer, é mais limpo e melhor fazê-lo explicitamente (ou seja, if err := someFunc(); err != nil { log.Fatal(err) }) em vez de uma função "auxiliar" que não está clara sobre o que está fazendo (o nome "Err" não é bom, não dá nenhuma indicação de que pode encerrar o programa).