Aunque la respuesta aceptada sigue siendo correcta sobre la necesidad de hacer coincidir los directorios con los nombres de los paquetes, realmente necesita migrar para usar los módulos Go en lugar de usar GOPATH. Los nuevos usuarios que enfrentan este problema pueden estar confundidos acerca de las menciones de usar GOPATH (como era yo), que ahora están desactualizadas. Por lo tanto, intentaré aclarar este problema y proporcionar orientación relacionada con la prevención de este problema al usar los módulos Go.
Si ya está familiarizado con los módulos Go y está experimentando este problema, vaya a mis secciones más específicas a continuación que cubren algunas de las convenciones Go que son fáciles de pasar por alto u olvidar.
Esta guía enseña sobre los módulos Go: https://golang.org/doc/code.html
Organización del proyecto con módulos Go
Una vez que migre a los módulos Go, como se menciona en ese artículo, organice el código del proyecto como se describe:
Un repositorio contiene uno o más módulos. Un módulo es una colección de paquetes Go relacionados que se lanzan juntos. Un repositorio Go generalmente contiene un solo módulo, ubicado en la raíz del repositorio. Un archivo llamado go.mod declara la ruta del módulo: el prefijo de ruta de importación para todos los paquetes dentro del módulo. El módulo contiene los paquetes en el directorio que contiene su archivo go.mod, así como los subdirectorios de ese directorio, hasta el siguiente subdirectorio que contiene otro archivo go.mod (si lo hay).
La ruta de cada módulo no solo sirve como un prefijo de ruta de importación para sus paquetes, sino que también indica dónde debe buscar el comando go para descargarlo. Por ejemplo, para descargar el módulo golang.org/x/tools, el comando go consultaría el repositorio indicado por https://golang.org/x/tools (descrito más aquí).
Una ruta de importación es una cadena utilizada para importar un paquete. La ruta de importación de un paquete es su ruta de módulo unida con su subdirectorio dentro del módulo. Por ejemplo, el módulo github.com/google/go-cmp contiene un paquete en el directorio cmp /. La ruta de importación de ese paquete es github.com/google/go-cmp/cmp. Los paquetes en la biblioteca estándar no tienen un prefijo de ruta de módulo.
Puede inicializar su módulo de esta manera:
$ go mod init github.com/mitchell/foo-app
Su código no necesita estar ubicado en github.com para que se pueda construir. Sin embargo, es una buena práctica estructurar sus módulos como si finalmente fueran publicados.
Comprender lo que sucede al intentar obtener un paquete
Aquí hay un gran artículo que habla sobre lo que sucede cuando intenta obtener un paquete o módulo: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
Discute dónde se almacena el paquete y lo hará ayudarle a comprender por qué podría recibir este error si ya está utilizando los módulos Go.
Asegúrese de que la función importada se haya exportado
Tenga en cuenta que si tiene problemas para acceder a una función desde otro archivo, debe asegurarse de haber exportado su función. Como se describe en el primer enlace que proporcioné, una función debe comenzar con una letra mayúscula para exportar y poner a disposición para importar a otros paquetes.
Nombres de directorios
Otro detalle crítico (como se mencionó en la respuesta aceptada) es que los nombres de directorios son los que definen los nombres de sus paquetes. (Los nombres de sus paquetes deben coincidir con los nombres de sus directorios). Puede ver ejemplos de esto aquí: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc
With Dicho esto, el archivo que contiene su main
método (es decir, el punto de entrada de su solicitud) está exento de este requisito.
Como ejemplo, tuve problemas con mis importaciones al usar una estructura como esta:
/my-app
├── go.mod
├── /src
├── main.go
└── /utils
└── utils.go
No pude importar el código en utils
mi main
paquete.
Sin embargo, una vez que lo puse main.go
en su propio subdirectorio, como se muestra a continuación, mis importaciones funcionaron bien:
/my-app
├── go.mod
├── /src
├── /app
| └── main.go
└── /utils
└── utils.go
En ese ejemplo, mi archivo go.mod se ve así:
module git.mydomain.com/path/to/repo/my-app
go 1.14
Cuando guardé main.go después de agregar una referencia a utils.MyFunction()
, mi IDE obtuvo automáticamente la referencia a mi paquete de esta manera:
import "git.mydomain.com/path/to/repo/my-app/src/my-app"
(Estoy usando VS Code con la extensión Golang).
Observe que la ruta de importación incluía el subdirectorio del paquete.
Tratar con un repositorio privado
Si el código es parte de un repositorio privado, debe ejecutar un comando git para habilitar el acceso. De lo contrario, puede encontrar otros errores Este artículo menciona cómo hacer eso para repositorios privados de Github, BitBucket y GitLab: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositorios-dfe795068db4
Este tema también se discute aquí: ¿Cuál es la forma correcta de "obtener" un repositorio privado?