Go: Funcional ou POO? Escolhendo o estilo de programação

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: O debate eterno no mundo Go

\n\n

Go — uma linguagem que quebrou paradigmas. Ela não perdoa complexidade excessiva, mas ao mesmo tempo dá ao desenvolvedor uma liberdade incrível. Todo mundo que começa a programar em Go (ou migra de Python ou Java) mais cedo ou mais tarde se depara com uma parede: “Qual é a maneira correta? Escrever como em Java com classes e herança ou como em Haskell com funções sem efeitos colaterais?”

\n\n

Spoiler: Go não é uma linguagem puramente orientada a objetos nem puramente funcional. Ela é pragmática. Mas isso não significa que você não pode (e não deve) usar ambos os paradigmas. Neste artigo, vamos analisar como combinar a abordagem funcional e orientada a objetos em Go para que seu código seja legível, testável e rápido. Não vamos dar palestras, mas sim ver exemplos reais e antipadrões.

\n\n

Se você está procurando melhores práticas em Go e quer entender como escrever código limpo nesta linguagem — está no lugar certo.

\n\n

1. Abordagem orientada a objetos em Go: Sem classes, mas com alma

\n\n

Muitos acreditam que, como Go não tem class, então POO não existe nele. Isso é um mito. POO em Go é construída sobre dois pilares: structs e interfaces. Não há herança, mas há composição, que os criadores da linguagem consideram mais flexível.

\n\n

Structs e métodos

\n

Você pode definir métodos para qualquer tipo. Essa é a base do código orientado a objetos.

\n\n
package main\n\nimport "fmt"\n\n// Definindo uma interface (contrato)\ntype Notifier interface {\n    Send(message string) error\n}\n\n// Struct implementando a interface\ntype EmailNotifier struct {\n    Email string\n}\n\n// Método para EmailNotifier\nfunc (e EmailNotifier) Send(message string) error {\n    fmt.Printf("Enviando email para %s: %s\\n", e.Email, message)\n    return nil\n}\n\n// Outra struct\ntype SMSNotifier struct {\n    Phone string\n}\n\nfunc (s SMSNotifier) Send(message string) error {\n    fmt.Printf("Enviando SMS para %s: %s\\n", s.Phone, message)\n    return nil\n}\n\n// Função que aceita qualquer Notifier (polimorfismo)\nfunc AlertAll(notifiers []Notifier, msg string) {\n    for _, n := range notifiers {\n        n.Send(msg)\n    }\n}\n\nfunc main() {\n    notifiers := []Notifier{\n        EmailNotifier{Email: "user@example.com"},\n        SMSNotifier{Phone: "+1234567890"},\n    }\n    AlertAll(notifiers, "Servidor caiu!")\n}
\n\n

Vantagens da POO em Go:

\n
    \n
  • Polimorfismo através de interfaces. Você escreve a função AlertAll uma vez, e ela funciona com qualquer tipo que implemente Notifier. Isso é baixo acoplamento.
  • \n
  • Estado. Structs são ideais para modelos de dados (User, Order, Config).
  • \n
  • Encapsulamento. Campos com letra minúscula são privados, com maiúscula são públicos. Simples e eficaz.
  • \n
\n\n

Desvantagens:

\n
    \n
  • Fácil cair no “estilo Java”: criar hierarquias profundas, embora Go não as suporte.
  • \n
  • Mutabilidade (alteração de estado) dificulta testes e depuração.
  • \n
\n\n

2. Programação funcional em Go: Pureza pela velocidade

\n\n

O estilo funcional em Go não é cálculo lambda, mas sim um conjunto de princípios: mínimo de efeitos colaterais, imutabilidade, funções como argumentos. Com o advento dos genéricos (Go 1.18+), esse estilo se tornou mais poderoso.

\n\n

Funções puras e imutabilidade

\n

A regra principal da programação funcional: a função recebe dados, retorna novos dados, mas não altera nada externamente.

\n\n
package main\n\nimport "fmt"\n\n// Ruim: mutando o slice de entrada (efeito colateral)\nfunc BadAddPrefix(users []string, prefix string) {\n    for i := range users {\n        users[i] = prefix + users[i]\n    }\n}\n\n// Bom: retornando um novo slice (função pura)\                

Blogs

Book Recommendations