Nomenclatura de Paquetes y Directorios internal/
Los nombres de los paquetes de Go y la disposición de los directorios comunican la intención antes de que un lector abra un archivo.
Busca en todas las páginas de la documentación
Los nombres de los paquetes de Go y la disposición de los directorios comunican la intención antes de que un lector abra un archivo.
Nombres cortos consistentes más los directorios internal/ mantienen honestas las APIs públicas y permiten que el compilador aplique los límites.
Los nombres de los paquetes deben ser en minúsculas, concisos y descriptivos sin repeticiones redundantes.
Las rutas de importación llevan el prefijo del módulo; las cláusulas de paquete nombran la unidad compilada.
El nombre especial internal restringe las importaciones a los directorios ancestros dentro del mismo árbol de módulos.
Esa combinación reduce el acoplamiento accidental y hace que las refactorizaciones sean más seguras para los autores de bibliotecas.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
// example.com/widget/internal/parser/parser.go
package parser // no es package widgetparser
import "strings"
func Parse(raw string) (string, error) {
return strings.TrimSpace(raw), nil
}// example.com/widget/api/handler.go
package api
import "example.com/widget/internal/parser"
func Handle(raw string) (string, error) {
return parser.Parse(raw)
}Cuándo usar esto:
auth, store, parser), no el nombre del repositorio.internal/ cuando los módulos externos no deben importarlos.cmd/ de paquetes reutilizables en el mismo módulo.go list o linters que marcan rutas repetitivas.example.com/checkout/
go.mod
cmd/checkoutd/main.go
checkout/ // tipos de dominio - la ruta de importación termina en /checkout
checkout.go
internal/
tax/
tax.go
payment/
payment.go
api/
http.go
// checkout/checkout.go
package checkout
type Cart struct {
Items []string
}// internal/tax/tax.go
package tax
func Rate(region string) float64 {
if region == "CA" {
return 0.0725
}
return 0
}// api/http.go
package api
import (
"example.com/checkout/checkout"
"example.com/checkout/internal/tax"
)
func Quote(c checkout.Cart, region string) float64 {
return tax.Rate(region) * float64(len(c.Items))
}Lo que esto demuestra:
internal/tax puede ser llamado desde api/ porque api está bajo el padre internal example.com/checkout.checkout y api pero no internal/tax.tax.Rate).Los nombres cortos se leen bien en los sitios de llamada porque la ruta de importación ya proporciona contexto.
internal solo cuando el paquete importador está debajo del directorio que contiene la carpeta internal.Para .../checkout/internal/tax, los importadores deben vivir debajo de .../checkout/.
package foo y package bar en la misma carpeta.| Regla | Razón |
|---|---|
| Minúsculas, sin guiones bajos | Coincide con el estilo de Go y la ergonomía de importación |
Sin util, common, misc | Los nombres deben indicar lo que hace el paquete |
Evitar repeticiones (http.HTTPServer de net/http es una excepción de la biblioteca estándar) | Los sitios de llamada se leen más limpios |
| Un paquete por directorio | El grafo de compilación y las pruebas se mantienen predecibles |
| Coincidir con el modelo mental de los importadores | El nombre del paquete encoding/json es json, no encodingjson |
| Directorio | Aplicación | Uso Típico |
|---|---|---|
internal/ | Aplicado por el compilador | Implementación privada, ayudantes inestables |
pkg/ | Solo por convención | API pública documentada para otros repositorios |
| Paquetes nombrados de nivel superior | Públicos por defecto | Modelos de dominio y bibliotecas estables |
pkg/ no oculta símbolos.
Si necesitas garantías sólidas, usa internal/.
// Malo: repetición en el sitio de llamada cuando la importación se renombra mal
import checkoutinternal "example.com/checkout/internal/checkout"
// Bueno: detalle interno con nombre de paquete corto
import "example.com/checkout/internal/tax"// internal/ anidado aún más profundo funciona - la regla es por directorio internal
// example.com/checkout/internal/payment/gateway/gateway.go
package gatewaymain y casos bien conocidos de la biblioteca estándar.internal se basa en la ruta, no en la visibilidad. Los identificadores en minúsculas ya son privados del paquete; internal/ bloquea las importaciones entre módulos por completo.internal/ es un cambio que rompe la compatibilidad para cualquiera que haya importado la ruta antigua.utils) se convierten en cajones de sastre. Divídalos por responsabilidad en su lugar.package foo_test viven junto a foo y son un paquete separado para pruebas de caja negra.internal/ cuando los equipos necesitan semver separados.internal/ entre módulos).El lenguaje lo permite, pero las guías de estilo y las herramientas esperan nombres de una sola palabra en minúsculas.
Los guiones bajos son raros y distraen en los bloques de importación.
Cualquier paquete cuyo directorio esté bajo example.com/checkout/, incluyendo api/ y cmd/checkoutd/.
Los paquetes en otros módulos no pueden, incluso si dependen de example.com/checkout.
Sí, en casi todos los casos.
La discrepancia (directorio mypkg, package foo) impone una sobrecarga mental y confunde a go doc.
No, muchos proyectos exportan paquetes desde la raíz del módulo o carpetas nombradas de nivel superior.
Usa pkg/ cuando quieras una zona obvia "soportada para uso externo".
Agrega la nueva ruta, reexporta o migra a los llamadores, depreca la ruta de importación antigua en las notas de lanzamiento y elimínala en una actualización mayor para bibliotecas.
Sí, internal solo restringe a los importadores externos, no a los hermanos bajo el mismo árbol.
Coloca los ayudantes en internal/testutil o exporta etiquetas de compilación solo para pruebas de forma limitada.
Evita que los binarios de producción importen paquetes de prueba.
go vet y linters como revive pueden marcar repeticiones y problemas de estilo.
Habilítalos en CI para mantener la consistencia.
Cada módulo tiene su propio árbol.
internal en el módulo A no se aplica al módulo B, incluso si ambos residen en el mismo repositorio Git.
Cuando oscurece el significado en los sitios de llamada.
Prefiere version o nombres específicos del dominio a menos que el alcance sea muy pequeño y local.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado Green Tea GC, go fix modernizadores - verificar parche en la compilación), chi (última versión - verificar en la compilación), gin (última versión - verificar en la compilación), echo (última versión - verificar en la compilación), google.golang.org/grpc (última versión - verificar en la compilación), sigs.k8s.io/controller-runtime (última versión - verificar en la compilación), kubebuilder (última versión - verificar en la compilación), tinygo (última versión - verificar objetivos de placa en la compilación), wazero (última versión - verificar en la compilación), y golangci-lint (última versión - verificar conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 18 jul 2026