Tratamento de erros em Go
Um dos primeiros pontos que causam estranheza para quem está começando em Go é a forma como os erros são tratados, principalmente quando viemos de outras linguagens orientadas a objetos. Em Go os erros são “first class citizens”, ou seja, eles não são ocultos ou delegados e são considerados parte importante do código.
Hoje passei por uma situação onde isso fez diferença. Revisando/debugando o código em PHP (alterado do original):
<?php
$response = $this->transmitter->transmit($nfe, $xml);
$xml = $this->transmitter->getNfeWithTransmissionResults();
$result = $this->transmitter->saveData($response, $xml);
Assume-se que o $response, por exemplo, deve retornar um valor correto, que qualquer erro seria tratado pelo método transmit e exceptions seriam geradas caso contrário.
Em Go o mesmo código poderia ser escrito da seguinte forma:
response, err := transmitter.transmit(nfe, xml)
if err != nil {
panic("Error ") //tratamento de erro qualquer
}
xml = transmitter.getNfeWithTransmissionResults()
result = transmitter.saveData(response, xml)
Como todo método pode retornar dois resultados, um de sucesso e outro de erro, podemos capturar e tratar o problema explicitamente.
A primeira impressão é que o código está mais burocrático e ferindo algum princípio como os defendidos pelo SOLID, mas o erro e seu tratamento está bem mais claro. E em uma linguagem de programação que tem como foco o desenvolvimento de aplicativos concorrentes isso pode ser uma grande vantagem.
Também é possível ignorar o erro usando:
response, _ := transmitter.transmit(nfe, xml)
xml = transmitter.getNfeWithTransmissionResults()
result = transmitter.saveData(response, xml)
E desta forma estamos delegando o controle para o método transmit, como no exemplo em PHP.
A “moral da história” aqui é entender as vantagens e desvantagens de cada abordagem para podermos escolher a melhor forma para implementá-la em nossos projetos.
Mais detalhes sobre o tratamento de erros em Go pode ser vista no blog oficial