Clean Code em Go: princípios e exemplos para iniciantes
Código limpo (Clean Code) não é um luxo, mas uma necessidade para qualquer desenvolvedor que trabalhe em equipe ou em projetos de longo prazo. Na linguagem Go (Golang), que é conhecida por sua simplicidade e eficiência, os princípios de código limpo são especialmente importantes. Neste artigo, vamos analisar os principais princípios do Clean Code com exemplos em Go, que ajudarão você a escrever código compreensível, sustentável e eficiente.
Por que o código limpo é importante em Go?
Go foi projetado como uma linguagem para criar sistemas escaláveis e sustentáveis. Sua sintaxe é minimalista e suas ferramentas (go fmt, go vet) já incentivam a uniformidade. No entanto, o código limpo vai além da formatação. Ele inclui:
- Legibilidade — o código deve ser compreensível para outro desenvolvedor (ou para você daqui a seis meses).
- Simplicidade — evite complexidade desnecessária.
- Testabilidade — código limpo é fácil de testar.
- Sustentabilidade — mudanças não quebram todo o sistema.
Princípio 1: Nomes compreensíveis para variáveis e funções
Nomes ruins são o principal inimigo do código limpo. Em Go, é comum usar nomes curtos, mas informativos. Evite variáveis de uma letra (exceto para índices de loops).
Exemplo ruim:
func f(x int) int { r := x * 2 return r}Exemplo bom:
func DoubleValue(value int) int { result := value * 2 return result}Em Go, também há um idioma: quanto menor o escopo, mais curto pode ser o nome. Por exemplo, em funções curtas, você pode usar i para índice, mas em escopo global, é melhor dar um nome significativo.
Princípio 2: Evite números e strings mágicos
Números mágicos (números sem explicação) tornam o código confuso. Use constantes.
Exemplo ruim:
func CalculatePrice(amount float64) float64 { return amount * 1.2 // O que é 1.2?}Exemplo bom:
const TaxRate = 0.2
func CalculatePrice(amount float64) float64 { return amount * (1 + TaxRate)}O mesmo vale para strings: coloque-as em constantes ou use enumerações (iota).
Princípio 3: Funções pequenas com uma única responsabilidade
Cada função deve fazer apenas uma coisa. Isso simplifica os testes e a leitura.
Exemplo ruim (função faz demais):
func ProcessOrder(order Order) error { // Validação if order.Amount <= 0 { return errors.New("invalid amount") } // Salvar no BD err := db.Save(order) if err != nil { return err } // Enviar email return sendEmail(order.Email, "Order confirmed")}Exemplo bom (divisão em funções pequenas):
func ProcessOrder(order Order) error { if err := validateOrder(order); err != nil { return err } if err := saveOrder(order); err != nil { return err } return sendConfirmationEmail(order)}
func validateOrder(order Order) error { if order.Amount <= 0 { return errors.New("invalid amount") } return nil}
func saveOrder(order Order) error { return db.Save(order)}
func sendConfirmationEmail(order Order) error { return sendEmail(order.Email, "Order confirmed")}Agora cada função pode ser testada separadamente, e o código ficou mais legível.
Princípio 4: Tratamento de erros (Error Handling)
Em Go, não há exceções; os erros são retornados como valores. O código limpo exige tratamento explícito e claro de erros.
Exemplo ruim (ignorando o erro):
result, _ := doSomething()fmt.Println(result)Exemplo bom:
result, err := doSomet