Ir a compilar: "No se puede encontrar el paquete" (aunque GOPATH está configurado)

139

Aunque lo he GOPATHconfigurado correctamente, todavía no puedo obtener "ir a compilar" o "ir a ejecutar" para encontrar mis propios paquetes. ¿Qué estoy haciendo mal?

$ echo $GOROOT
/usr/local/go

$ echo $GOPATH
/home/mitchell/go

$ cat ~/main.go
package main
import "foobar"
func main() { }

$ cat /home/mitchell/go/src/foobar.go
package foobar

$ go build main.go
main.go:3:8: import "foobar": cannot find package
Ensalada Mitchell
fuente
Me encuentro con el mismo problema cuando voy a obtener github.com/adonovan/gopl.io/tree/master/ch1/helloworld La razón será que no tiene un archivo de nombre helloworld.go. ir a trabajar haciendo coincidir el nombre del paquete y el nombre del archivo.
keniee van
También puede ser que necesites actualizar Go. Tuve un problema similar en el que tenía código existente usando go.mod para definir un módulo. En una máquina de prueba había descargado el código y estaba tratando de compilarlo, pero Go me estaba dando todo tipo de errores relacionados con GOPATH y no podía encontrar módulos. Era Go versión 1.7. Tan pronto como actualicé Go, funcionó sin problemas.
KyferEz
Escriba esto es terminal para obtener una explicación actualizada$ go help gopath
A1rPun

Respuestas:

162

No funciona porque su foobar.goarchivo fuente no está en un directorio llamado foobar. go builde go installintente hacer coincidir los directorios, no los archivos de origen.

  1. Establecer $GOPATHen un directorio válido, p. Ej.export GOPATH="$HOME/go"
  2. Mover foobar.goa $GOPATH/src/foobar/foobar.goy la construcción debería funcionar bien.

Pasos adicionales recomendados:

  1. Añadir $GOPATH/bina tu $PATHpor:PATH="$GOPATH/bin:$PATH"
  2. Moverse main.goa una subcarpeta de $GOPATH/src, p. Ej.$GOPATH/src/test
  3. go install testahora debe crear un ejecutable en el $GOPATH/binque se pueda llamar escribiendo testen su terminal.
fasmat
fuente
1
¿No es esto un error? Mi GOPATH=/usr/local/go-pkgs, así que Go busca /usr/local/go-pkgs/src/<package-name>la fuente, pero la go getcoloca /usr/local/go-pkgs/src/gopkg.in/<package-name>. ¿Por qué debería tener que mover manualmente todos mis paquetes después de la instalación? Eso es una tontería.
josiah
3
go getnormalmente pone paquetes en, $GOPATH/src/así que si llamas go get domain.com/path/to/packageterminará en $GOPATH/src/domain.com/path/to/package. ¿Supongo que intentas buscar un paquete gopkg.in? Si es así, ese es un comportamiento absolutamente intencionado y solo debe importarlos con su nombre completo; por ejemplo, import "gopkg.in/yaml.v1"como también se describe en los documentos .
fasmat
1
Ahhhh, ya veo. Gracias por disipar mi ignorancia.
josiah
10

Editar: ya que te referías a GOPATH, mira la respuesta de fasmat (upvoted)

Como se menciona en " ¿Cómo hago para encontrar mi paquete? ", Debe colocar un paquete xxxen un directorioxxx .

Ver las especificaciones del idioma Go :

package math

Un conjunto de archivos que comparten la misma PackageNameforma de implementación de un paquete.
Una implementación puede requerir que todos los archivos fuente de un paquete habiten en el mismo directorio.

La organización del Código menciona:

Al construir un programa que " widget" importa el paquete, el gocomando busca src/pkg/widgetdentro de la raíz Go y luego, si no se encuentra el origen del paquete, busca src/widgetdentro de cada espacio de trabajo en orden.

(un "espacio de trabajo" es una entrada de ruta en su GOPATH: esa variable puede hacer referencia a múltiples rutas para que su ' src, bin, pkg' sea)


(Respuesta original)

También debe establecer GOPATH~ / go, no GOROOT, como se ilustra en " Cómo escribir el código Go ".

La ruta Go se usa para resolver declaraciones de importación. Está implementado y documentado en el paquete go / build.

La GOPATHvariable de entorno enumera los lugares para buscar el código Go.
En Unix, el valor es una cadena separada por dos puntos.
En Windows, el valor es una cadena separada por punto y coma.
En el Plan 9, el valor es una lista.

Eso es diferente de GOROOT:

Las distribuciones binarias Go suponen que se instalarán en /usr/local/go(o c:\Gobajo Windows), pero es posible instalarlas en una ubicación diferente.
Si hace esto, deberá establecer la GOROOTvariable de entorno en ese directorio cuando use las herramientas Go.

VonC
fuente
44
También hay una breve introducción de video para configurar el GOPATH
Ulf Holm Nielsen
1
Lo siento, he editado la pregunta original. En todas partes dije GOROOT quise decir GOPATH.
MitchellSalad el
3

TL; DR: ¡ Sigue las convenciones de Go! (Lección aprendida de la manera difícil), verifique las versiones anteriores de go y elimínelas . Instalar lo último.

Para mí la solución fue diferente. Trabajé en un servidor Linux compartido y después de verificar mi GOPATHy otras variables de entorno varias veces todavía no funcionó. Encontré varios errores que incluyen 'No se puede encontrar el paquete' y 'ruta de importación no reconocida'. Después de intentar reinstalar con esta solución siguiendo las instrucciones en golang.org (incluida la parte de desinstalación ), aún se encontraron problemas.

Me tomó un tiempo para darse cuenta de que todavía hay una versión antigua que no ha sido desinstalado (que se ejecuta go versiona continuación, which gode nuevo ... dahh), que me llevó a esta pregunta y, finalmente resuelto.

Moshisho
fuente
2

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 mainmé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 utilsmi mainpaquete.

Sin embargo, una vez que lo puse main.goen 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?

devinbost
fuente
-6

¿Has intentado agregar el directorio absoluto de go to your 'path'?

export PATH=$PATH:/directory/to/go/
RobEdouard
fuente
$ PATH no tiene nada que ver con tu ruta para los paquetes go.
csgeek