Ciclos de Importação, Importações Vazias e Importações de Ponto
Go proíbe ciclos de importação em tempo de compilação.
Busque em todas as páginas da documentação
Go proíbe ciclos de importação em tempo de compilação.
Importações vazias executam o init do pacote para efeitos colaterais de registro, enquanto importações de ponto mesclam nomes exportados no namespace do importador e são desencorajadas em código de produção.
Um ciclo de importação ocorre quando o pacote A importa B e B importa A (direta ou através de uma cadeia).
O compilador rejeita ciclos porque a ordem de inicialização seria indefinida.
Importações vazias (import _ "pkg") são apenas para efeitos colaterais.
Importações de ponto (import . "pkg") expõem identificadores exportados sem um qualificador e prejudicam a legibilidade.
Cartão de receita de referência rápida - pronto para copiar e colar.
package main
import (
"fmt"
_ "image/png" // registra o decodificador PNG via init
)
func main() {
fmt.Println("decodificadores registrados")
}Quando usar isso:
init.Quebrando um ciclo com um pacote de contratos compartilhado:
example.com/app/
service/service.go
store/store.go
contract/contract.go
// contract/contract.go - sem importações de service ou store
package contract
type User struct {
ID string
}
type Repository interface {
Save(u User) error
}// store/store.go
package store
import "example.com/app/contract"
type Memory struct{}
func (Memory) Save(u contract.User) error { return nil }// service/service.go
package service
import (
"example.com/app/contract"
"example.com/app/store"
)
func Run() {
var repo contract.Repository = store.Memory{}
_ = repo.Save(contract.User{ID: "1"})
}O que isso demonstra:
service e store dependem de contract, não um do outro.contract).service.Ciclos de importação: O compilador constrói um DAG de pacotes.
Qualquer aresta de retorno falha a compilação com import cycle not allowed.
Refatore movendo tipos, interfaces ou funções compartilhadas para uma camada inferior que ambos os lados importam.
Importações vazias: O compilador ainda vincula o pacote e executa todas as funções init na ordem de dependência antes de main.
Usos típicos:
database/sqlimage/*Importações de ponto: import . "fmt" permite que você escreva Println em vez de fmt.Println.
O estilo Go rejeita isso em código de aplicação porque grep e leitores perdem o contexto do pacote.
| Padrão | Mover o quê | Troca |
|---|---|---|
| Extrair interfaces | Tipos de API voltados para o consumidor | Arquivo de pacote extra |
| Extrair DTOs | Structs compartilhadas | Pode ampliar a superfície da API |
| Injeção de dependência | Construir grafos em main | Mais "fiação" em cmd/ |
| Hooks de eventos/callbacks | Inverter a direção da dependência | Mais difícil de rastrear o fluxo |
// Importação vazia - apenas efeito colateral
import _ "github.com/lib/pq"// Importação de ponto - evite em código de aplicação
import . "example.com/app/config" // permite Port em vez de config.Port// Detectar ciclos cedo
// go build ./... relata a cadeia de caminhos de importaçãoimport . "foo") ainda confundem leitores; prefira qualificadores explícitos.foo_test podem importar foo e vizinhos; projete pacotes de produção para permanecerem acíclicos.init - registry.Register("png", decode) chamado de main para clareza.cmd/ sem importações mútuas.A inicialização do pacote é executada antes de main.
Um ciclo deixaria alguns pacotes semi-inicializados sem uma ordem segura.
Quando um pacote existe unicamente para se registrar em um registro global no tempo de init e seu código nunca o chama diretamente.
Sim, se ele expuser efeitos colaterais de init.
Prefira configuração explícita em main para a montagem da aplicação, a menos que esteja imitando padrões de driver.
Raramente em testes ou código gerado.
Código de produção deve usar identificadores qualificados de acordo com os Comentários de Revisão de Código Go.
Leia o erro do go build - ele imprime a cadeia de importação.
Corrija a preocupação compartilhada mais baixa primeiro.
Apenas quando a interface vive em um pacote que nenhum dos lados importa ciclicamente.
Ambos os lados podem depender do pacote de contratos.
Ainda um cheiro de design mesmo sem um ciclo.
Passe dependências explicitamente ou via construtores.
Pacotes de teste externos são unidades de compilação separadas.
Mantenha pacotes de produção acíclicos; testes têm mais flexibilidade, mas não devem impulsionar layouts ruins.
Não - pacotes da biblioteca padrão não importam seu código.
Ciclos aparecem no grafo do seu próprio módulo.
Frameworks às vezes registram rotas via init.
Tabelas de rotas explícitas em main ou internal/server são mais fáceis de auditar.
Versões de Stack: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, modernizadores go fix - 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