Composição de interfaces e boas práticas
Interfaces pequenas e inversão de dependências
Composição de interfaces e boas práticas é uma aula grátis de Go Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Go Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Go Academy inclui 4 aulas no total.
Composição de interfaces
As interfaces de Go podem incorporar outras interfaces para compor interfaces maiores:
package main
import "io"
// io.ReadWriter composes Reader and Writer
type ReadWriter interface {
io.Reader
io.Writer
}
// Your own composition:
type Processor interface {
io.Reader
Process() error
io.Closer
}
func main() { _ = (*Processor)(nil) }Princípio das interfaces pequenas
As interfaces mais poderosas de Go têm um ou dois métodos. Isso maximiza o número de tipos que podem satisfazê-las:
io.Reader— 1 métodoio.Writer— 1 métodoerror— 1 métodofmt.Stringer— 1 método
Interfaces grandes são mais difíceis de simular e testar.
Inversão de dependência
Aceite interfaces nos parâmetros das funções em vez de tipos concretos. Isso desacopla seu código de implementações específicas:
package main
import "fmt"
type Store interface {
Get(key string) (string, bool)
Set(key, val string)
}
func cache(s Store, key, value string) {
if _, ok := s.Get(key); !ok {
s.Set(key, value)
}
}
type MapStore struct{ m map[string]string }
func (ms *MapStore) Get(k string) (string, bool) { v, ok := ms.m[k]; return v, ok }
func (ms *MapStore) Set(k, v string) { ms.m[k] = v }
func main() {
s := &MapStore{m: map[string]string{}}
cache(s, "x", "hello")
v, _ := s.Get("x")
fmt.Println(v)
}Segregação de interfaces
Divida interfaces grandes em interfaces menores e focadas. Os clientes dependem apenas dos métodos que usam:
package main
// Bad: large interface forces all methods
type BigStorage interface {
Read(key string) string
Write(key, val string)
Delete(key string)
List() []string
Backup() error
}
// Good: small, focused interfaces
type Reader interface{ Read(key string) string }
type Writer interface{ Write(key, val string) }
type Lister interface{ List() []string }
func readAll(r Reader) {} // only needs Read
func main() { _ = readAll }Retorno de tipos concretos
Os construtores devem retornar tipos concretos, não interfaces. Os chamadores sempre podem atribuir um tipo concreto a uma variável de interface:
package main
type Logger interface{ Log(string) }
type ConsoleLogger struct{}
func (c *ConsoleLogger) Log(s string) {}
// Good: return concrete *ConsoleLogger
func NewConsoleLogger() *ConsoleLogger { return &ConsoleLogger{} }
// Avoid: return Logger (hides the concrete type)
// func NewConsoleLogger() Logger { return &ConsoleLogger{} }
func main() { _ = NewConsoleLogger() }Poluição de interfaces
Não crie uma interface para cada tipo "por precaução". Crie interfaces somente quando:
- Você tem várias implementações agora ou em breve
- Precisa simular a dependência nos testes
- Está criando uma biblioteca e quer desacoplar os chamadores
Incorporação de interfaces para extensão
Incorpore uma interface para adicionar métodos opcionais com implementações padrão:
package main
import "fmt"
type Handler interface{ Handle(msg string) }
type NamedHandler interface {
Handler
Name() string
}
func dispatch(h Handler) {
if nh, ok := h.(NamedHandler); ok {
fmt.Printf("[%s] ", nh.Name())
}
h.Handle("event")
}
type MyHandler struct{}
func (m MyHandler) Handle(msg string) { fmt.Println(msg) }
func (m MyHandler) Name() string { return "my" }
func main() { dispatch(MyHandler{}) }Simulação com interfaces
Defina as dependências como interfaces; injete simulações nos testes:
package main
import "fmt"
type Clock interface{ Now() int64 }
type MockClock struct{ T int64 }
func (m MockClock) Now() int64 { return m.T }
func isExpired(c Clock, expiresAt int64) bool {
return c.Now() > expiresAt
}
func main() {
mc := MockClock{T: 1000}
fmt.Println(isExpired(mc, 500)) // true
fmt.Println(isExpired(mc, 1500)) // false
}Incorporação de interfaces versus estruturas para reutilização
Use a incorporação de interfaces para compor APIs e a incorporação de estruturas para reutilizar código. Elas têm finalidades diferentes e não devem ser confundidas.
Detecção da conformidade com interfaces em tempo de compilação
Use uma verificação em tempo de compilação com um identificador em branco para confirmar que seu tipo satisfaz uma interface:
package main
type Doer interface{ Do() }
type MyType struct{}
func (m *MyType) Do() {}
// Compile-time check — no runtime cost
var _ Doer = (*MyType)(nil)
func main() {}Verificação rápida
Quando você deve definir uma nova interface em Go?
Recapitulação: práticas recomendadas para interfaces
Principais conclusões:
- Mantenha as interfaces pequenas — um ou dois métodos
- Componha interfaces a partir de interfaces menores
- Aceite interfaces e retorne tipos concretos
- Crie interfaces para facilitar os testes e permitir várias implementações
- Use uma verificação em tempo de compilação por atribuição a um identificador em branco
Proposta de prática
Projete uma interface Notifier com Notify(msg string) error. Implemente-a para EmailNotifier e SMSNotifier. Escreva uma função broadcast que envie para um []Notifier.
Perguntas Frequentes
A aula “Composição de interfaces e boas práticas” é grátis?
Sim — o texto completo de “Composição de interfaces e boas práticas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Go Academy, atualize para CoddyKit PRO. O curso de Go Academy inclui 4 aulas no total.
O que vou aprender em “Composição de interfaces e boas práticas”?
Interfaces pequenas e inversão de dependências Você pratica Go Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Go Academy?
Nenhuma experiência prévia é necessária. Go Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Composição de interfaces e boas práticas”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Go Academy?
Sim. Cada aula de Go Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Definindo e implementando interfaces
- Interfaces essenciais da biblioteca padrão
- Asserções de tipo e switches de tipo
- Composição de interfaces e boas práticas