Interfaces em Go: introdução prática
Desvende o funcionamento das interfaces em Go com explicações diretas, metáforas simples e exemplos práticos de código.
O que é uma interface em Go?
Em Go, uma interface define um conjunto de métodos que um tipo precisa implementar para
ser considerado compatível com ela. Diferente de linguagens como Java, essa
implementação é implícita: se um tipo possui os métodos pedidos, ele é automaticamente
aceito.
Atenção
Interfaces não conhecem implementações. Elas apenas exigem a presença de métodos
específicos — um verdadeiro contrato de comportamento.
Metáfora simples: o contrato do jogador
Pense em um jogador de futebol assinando com um clube. O contrato não exige saber a
posição do atleta, mas apenas que ele jogue conforme acordado. Interfaces seguem esse
mesmo conceito: o que importa é o que será feito, não como ou por quem.
Atenção
Ao usar interfaces, você foca nos comportamentos esperados e não na implementação
concreta. Isso reduz o acoplamento e permite mais flexibilidade no código.
Definindo comportamentos com interfaces
Suponha uma interface chamada Animal com um método FazerBarulho. Cachorros implementam
latido, gatos fazem miau — cada um à sua maneira. O programa apenas exige que eles façam
barulho, não importa como.
Interface implícita em Go
Em Go, basta um tipo implementar os métodos da interface para que ele seja compatível.
Isso simplifica o código e aumenta a flexibilidade; sempre que um tipo definir todos os
métodos esperados, ele passa a satisfazer a interface.
Polimorfismo em ação
Interfaces permitem tratar objetos diferentes de forma uniforme. Com uma interface Forma
que define o método Área, podemos utilizar tanto Círculo quanto Quadrado sem precisar se
preocupar com as diferenças internas de cálculo.
Info Extra
Isso é polimorfismo: múltiplos tipos com comportamentos distintos, tratados de maneira
uniforme.
Desacoplamento com interfaces
Interfaces estabelecem fronteiras claras entre partes do sistema. Arquiteturas como
Ports and Adapters se baseiam nesse princípio, permitindo a troca de implementações com
mínimo impacto, desde que o contrato continue sendo respeitado.
Métodos implementados: exemplo prático
- Passo 1: Criar struct Quadrado com campo Lado do tipo float64
- Passo 2: Criar struct Círculo com campo Raio
- Passo 3: Adicionar método Área() para cada struct, retornando o
cálculo específico - Passo 4: Criar interface Forma com assinatura do método Área
- Passo 5: Criar função calcularArea(Forma) que recebe a
interface como parâmetro
Expandindo Interfaces com múltiplos métodos
Podemos evoluir a interface Forma e incluir também o método Perímetro. Se um tipo não
implementar todos os métodos, ele será incompatível.
Erro comum
Remover um dos métodos do tipo — como Perímetro — gera erro de compilação, pois o
contrato não é mais respeitado.
Funções genéricas usando interfaces
Ao receber uma interface como parâmetro, uma função passa a aceitar qualquer tipo
compatível. Isso reduz duplicação e centraliza comportamentos.
Testes com interfaces simuladas
Interfaces também facilitam testes unitários. Você pode criar uma implementação falsa
(mock) do contrato para simular comportamentos sem depender de funções reais.
Dica de Teste
Crie mocks que retornam valores previsíveis e use-os para validar a lógica de funções
que dependem da interface.
Interfaces e Clean Architecture
Em arquiteturas limpas, interfaces separam comportamentos das dependências externas.
Isso aumenta a testabilidade do domínio e a flexibilidade nas trocas de componentes.
Bindings dinâmicos com interface
Go permite alternar contexto de execução usando interfaces. Basta o tipo seguir a
assinatura desejada. O binding (ligação) é automático e dinâmico.
Encapsulamento com interface
A implementação de métodos fica escondida do restante do software. O código depende
apenas da interface, promovendo encapsulamento natural.
Mudanças para crescimento do projeto
Conforme o projeto cresce, o uso de interfaces permite adicionar novas formas,
comportamentos e algoritmos sem afetar as dependências existentes.
Resumo das boas práticas
Defina interfaces pequenas, bem nomeadas, com comportamentos específicos. Não exponha
métodos desnecessários. Use composição para combiná-las em casos complexos.
Checklist de Implementação
- Criou structs com comportamentos distintos
- Implementou métodos com receivers apropriados
- Declarou interface com os métodos corretos
- Usou interface como parâmetro em funções
- Testou chamada polimórfica com tipos diferentes
- Criou mocks para simular comportamentos
- Validou erros na ausência de métodos obrigatórios