Definindo e Implementando Interfaces
Interfaces em Go descrevem comportamento através de conjuntos de métodos satisfeitos implicitamente por tipos concretos.
Busque em todas as páginas da documentação
Interfaces em Go descrevem comportamento através de conjuntos de métodos satisfeitos implicitamente por tipos concretos.
Defina interfaces pequenas no consumidor, aceite-as em parâmetros de função e retorne structs concretas de construtores.
Um valor de interface armazena um par tipo dinâmico e valor dinâmico.
A satisfação é verificada em tempo de compilação na atribuição; não existe palavra-chave implements.
Interfaces pequenas (frequentemente um ou dois métodos) mantêm mocks enxutos e incentivam a composição em vez de abstrações amplas.
Aceite interfaces, retorne structs é a regra principal da API: dependa do comportamento mínimo em parâmetros; exponha tipos concretos de funções New para que os chamadores não fiquem presos atrás de suas definições de interface.
Evite exportar interfaces grandes de pacotes produtores - elas se tornam contratos de compatibilidade problemáticos.
Cartão de referência rápida - pronto para copiar e colar.
// Pacote consumidor define o que ele precisa.
type Storage interface {
Get(ctx context.Context, key string) ([]byte, error)
Put(ctx context.Context, key string, value []byte) error
}
// Produtor retorna tipo concreto.
type MemStore struct {
mu sync.RWMutex
m map[string][]byte
}
func NewMemStore() *MemStore {
return &MemStore{m: make(map[string][]byte)}
}
func (s *MemStore) Get(ctx context.Context, key string) ([]byte, error) { /* ... */ }
func (s *MemStore) Put(ctx context.Context, key string, value []byte) error { /* ... */ }
func LoadConfig(ctx context.Context, store Storage, key string) ([]byte, error) {
return store.Get(ctx, key)
}Quando usar isso:
io.Reader, io.Writer).Handler, gRPC ServerStream).package notify
import (
"context"
"fmt"
)
type Sender interface {
Send(ctx context.Context, to, body string) error
}
type Service struct {
sender Sender
}
func New(sender Sender) *Service {
return &Service{sender: sender}
}
type LogSender struct{}
func (LogSender) Send(ctx context.Context, to, body string) error {
fmt.Printf("to=%s body=%q\n", to, body)
return nil
}
type SMTPClient struct {
host string
}
func NewSMTP(host string) *SMTPClient {
return &SMTPClient{host: host}
}
func (c *SMTPClient) Send(ctx context.Context, to, body string) error {
// dial c.host, send message ...
return nil
}
func (s *Service) Welcome(ctx context.Context, email string) error {
return s.sender.Send(ctx, email, "welcome")
}O que isso demonstra:
Sender vive com o consumidor Service, não com o pacote SMTP.New aceita Sender para injeção; retorna o tipo concreto *Service.M é satisfeito por qualquer tipo cujo conjunto de métodos inclua M.any contém todos os tipos; use apenas em limites de decodificação.io.ReadCloser.| Regra | Racional |
|---|---|
| Definir no consumidor | Produtores permanecem independentes |
| Manter 1-3 métodos | Fakes pequenos, evolução mais fácil |
| Nomear por capacidade | Storage, Sender, não IStorage |
Retornar structs de New | Chamadores não são forçados a importar tipos de interface |
| Documentar comportamento nil | Especialmente para interfaces retornadas |
| Interface | Métodos | Implementadores Típicos |
|---|---|---|
io.Reader | Read | Arquivos, buffers, rede |
fmt.Stringer | String | Tipos de domínio para logging |
error | Error | Sentinelas, erros encapsulados |
http.Handler | ServeHTTP | Roteadores, manipuladores chi/gin/echo |
// Divida interfaces quando os métodos não estiverem relacionados.
type Reader interface { Read(p []byte) (int, error) }
type Writer interface { Write(p []byte) (int, error) }
type ReadWriter interface {
Reader
Writer
}Prefira embutir em vez de interfaces únicas inchadas.
*Concreto a menos que a abstração seja o produto.== nil. Correção: retorne tipos concretos ou documente verificações com reflexão/padrões errors.Is.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Parâmetro de função | Hook único (Validator func() error) | Múltiplos métodos coordenados |
| Restrição de genéricos | Algoritmos compartilhados sobre tipos | Troca de plugins em tempo de execução |
| Apenas tipo concreto | Implementação única para sempre | Necessidade de testes com fakes |
any + type switch | Registro de plugins JSON | APIs de domínio estáveis |
Declare métodos com nomes e assinaturas correspondentes.
O compilador verifica na atribuição - nenhuma declaração explícita.
No pacote que usa o comportamento, não no pacote que fornece implementações.
Exceção: idiomatismos da biblioteca padrão como io.Reader definem contratos compartilhados.
Frequentemente um método (Reader, Writer, Stringer).
Adicione métodos apenas quando os chamadores realmente precisarem deles juntos.
Não - apenas métodos.
Compartilhe dados através de structs concretas passadas junto com interfaces ou valores retornados.
Ambos os slots de tipo e valor estão desdefinidos.
Diferente de uma interface contendo um ponteiro nil tipado.
Em pacotes de aplicação, sim - para duplos de teste.
Em CLIs simples com um único banco de dados, um tipo concreto pode ser suficiente até que os testes exijam fakes.
Use interfaces geradas ou wrappers estreitos em torno de métodos RPC específicos.
Evite fazer mock de structs de cliente inteiras geradas quando um método importa.
É uma alteração que quebra a compatibilidade para implementadores externos.
Introduza um novo nome de interface ou uma interface não exportada dentro do seu pacote.
errors.As verifica se um erro implementa uma interface e o extrai.
Defina interfaces sentinela para classificação com moderação.
Prefira interfaces http.Handler para portabilidade entre adaptadores chi, gin, echo.
Tipos de framework vazam quando usados como limites de domínio.
Métodos não exportados em interfaces restringem a implementação ao seu pacote.
Útil para selar implementações enquanto exporta o tipo de interface.
Linters como iface detectam interfaces não utilizadas e sugerem remoção.
ireturn pode sinalizar funções que retornam interfaces - alinhe-se com o estilo da equipe.
Versões de Stack: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, go fix modernizers - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 18 de jul. de 2026