Go build: "Impossibile trovare il pacchetto" (anche se GOPATH è impostato)


139

Anche se ho GOPATHimpostato correttamente, non riesco ancora a trovare "go build" o "go run" per trovare i miei pacchetti. Che cosa sto facendo di sbagliato?

$ 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

Incontro lo stesso problema quando vado a prendere github.com/adonovan/gopl.io/tree/master/ch1/helloworld Il motivo deve essere che non ha file di nome helloworld.go. go get funziona abbinando il nome del pacchetto e il nome file.
Keniee van

Potrebbe anche essere necessario aggiornare Go. Ho avuto un problema simile in cui avevo un codice esistente usando go.mod per definire un modulo. Su una macchina di prova avevo scaricato il codice e stavo cercando di compilarlo, ma Go mi stava dando tutti i tipi di errori relativi a GOPATH e non riuscivo a trovare i moduli. Era Go versione 1.7. Non appena ho aggiornato Go, ha funzionato senza problemi.
KyferEz,

Digita questo terminale per una spiegazione aggiornata$ go help gopath
A1rPun

Risposte:


162

Non funziona perché il foobar.gofile sorgente non si trova in una directory chiamata foobar. go builde go installprova ad abbinare le directory, non i file sorgente.

  1. Impostare $GOPATHsu una directory valida, ad esexport GOPATH="$HOME/go"
  2. Spostare foobar.goa $GOPATH/src/foobar/foobar.goe la costruzione dovrebbe funzionare bene.

Passaggi aggiuntivi consigliati:

  1. Aggiungi $GOPATH/binal tuo $PATHdi:PATH="$GOPATH/bin:$PATH"
  2. Passa main.goa una sottocartella di $GOPATH/src, ad es$GOPATH/src/test
  3. go install testora dovrebbe creare un eseguibile $GOPATH/binche può essere chiamato digitando testnel tuo terminale.

1
Non è un bug? Mio GOPATH=/usr/local/go-pkgs, quindi Go cerca /usr/local/go-pkgs/src/<package-name>la fonte, ma la go getinserisce /usr/local/go-pkgs/src/gopkg.in/<package-name>. Perché dovrei spostare manualmente tutti i miei pacchetti dopo l'installazione? È solo stupido.
josiah,

3
go getnormalmente inserisce i pacchetti, $GOPATH/src/quindi se lo chiami go get domain.com/path/to/packagefinirà $GOPATH/src/domain.com/path/to/package. Immagino che provi a prendere un pacchetto da gopkg.in? In tal caso è un comportamento assolutamente previsto e dovresti semplicemente importarli con il loro nome completo; ad es. import "gopkg.in/yaml.v1"come descritto anche nei documenti .
fasmat,

1
Ahhhh, capisco. Grazie per aver dissipato la mia ignoranza.
josiah,

10

Edit: dal momento che si intende GOPATH, vedere fasmat 's risposta (upvoted)

Come accennato in " Come posso trovare il mio pacchetto? ", È necessario inserire un pacchetto xxxin una directory xxx.

Vedi le specifiche della lingua Go :

package math

Un insieme di file che condividono la stessa PackageNameforma dell'implementazione di un pacchetto.
Un'implementazione può richiedere che tutti i file di origine per un pacchetto si trovino nella stessa directory.

L' organizzazione del codice menziona:

Quando si crea un programma che importa il pacchetto " widget", il gocomando cerca src/pkg/widgetall'interno della radice Go e quindi, se l'origine del pacchetto non viene trovata lì, cerca src/widgetall'interno di ogni area di lavoro in ordine.

(uno "spazio di lavoro" è una voce di percorso nel tuo GOPATH: quella variabile può fare riferimento a più percorsi affinché il tuo ' src, bin, pkg' sia)


(Risposta originale)

Dovresti anche impostare GOPATHsu ~ / go, non GOROOT, come illustrato in " Come scrivere il codice Go ".

Il percorso Vai viene utilizzato per risolvere le dichiarazioni di importazione. È implementato e documentato nel pacchetto go / build.

La GOPATHvariabile d'ambiente elenca i luoghi in cui cercare il codice Go.
Su Unix, il valore è una stringa separata da due punti.
Su Windows, il valore è una stringa separata da punto e virgola.
Nel piano 9, il valore è un elenco.

Questo è diverso da GOROOT:

Le distribuzioni binarie Go presuppongono che saranno installate in /usr/local/go(o c:\Gosotto Windows), ma è possibile installarle in una posizione diversa.
In questo caso, sarà necessario impostare la GOROOTvariabile di ambiente su quella directory quando si utilizzano gli strumenti Go.


4
C'è anche un breve video introduttivo per la creazione del GOPATH
Ulf Holm Nielsen,

1
Mi dispiace, ho modificato la domanda originale. Ovunque dicessi GOROOT intendevo GOPATH.
MitchellSalad,

3

TL; DR: seguire le convenzioni Go! (lezione imparata nel modo più duro), controlla le versioni precedenti e rimuovile . Installa l'ultima.

Per me la soluzione era diversa. Ho lavorato su un server Linux condiviso e dopo aver verificato GOPATHpiù volte la mia e altre variabili di ambiente non funzionava ancora. Ho riscontrato diversi errori tra cui "Impossibile trovare il pacchetto" e "Percorso di importazione non riconosciuto". Dopo aver provato a reinstallare con questa soluzione seguendo le istruzioni su golang.org (inclusa la parte di disinstallazione ), ho ancora riscontrato problemi.

Mi ci è voluto un po 'di tempo per rendermi conto che c'è ancora una vecchia versione che non è stata disinstallata (in esecuzione go versionpoi di which gonuovo ... DAHH) che mi ha portato a questa domanda e finalmente risolto.


2

Sebbene la risposta accettata sia ancora corretta sulla necessità di abbinare le directory con i nomi dei pacchetti, è necessario migrare all'utilizzo dei moduli Go invece di utilizzare GOPATH. I nuovi utenti che riscontrano questo problema potrebbero essere confusi riguardo alle menzioni dell'uso di GOPATH (come lo ero io), che ora sono obsolete. Quindi, proverò a risolvere questo problema e fornirò una guida per prevenire questo problema quando si utilizzano i moduli Go.

Se hai già familiarità con i moduli Go e riscontri questo problema, passa alle mie sezioni più specifiche di seguito che trattano alcune delle convenzioni Go che sono facili da ignorare o dimenticare.

Questa guida spiega i moduli Go: https://golang.org/doc/code.html

Organizzazione del progetto con moduli Go

Una volta eseguita la migrazione ai moduli Go, come menzionato in quell'articolo, organizza il codice del progetto come descritto:

Un repository contiene uno o più moduli. Un modulo è una raccolta di pacchetti Go correlati che vengono rilasciati insieme. Un repository Go contiene in genere un solo modulo, situato nella radice del repository. Un file chiamato go.mod lì dichiara il percorso del modulo: il prefisso del percorso di importazione per tutti i pacchetti all'interno del modulo. Il modulo contiene i pacchetti nella directory contenente il suo file go.mod e le sue sottodirectory, fino alla successiva sottodirectory contenente un altro file go.mod (se presente).

Il percorso di ogni modulo non serve solo come prefisso del percorso di importazione per i suoi pacchetti, ma indica anche dove dovrebbe essere il comando go per scaricarlo. Ad esempio, per scaricare il modulo golang.org/x/tools, il comando go dovrebbe consultare il repository indicato da https://golang.org/x/tools (descritto di più qui).

Un percorso di importazione è una stringa utilizzata per importare un pacchetto. Il percorso di importazione di un pacchetto è il percorso del suo modulo unito alla sua sottodirectory all'interno del modulo. Ad esempio, il modulo github.com/google/go-cmp contiene un pacchetto nella directory cmp /. Il percorso di importazione di quel pacchetto è github.com/google/go-cmp/cmp. I pacchetti nella libreria standard non hanno un prefisso di percorso del modulo.

Puoi inizializzare il tuo modulo in questo modo:

$ go mod init github.com/mitchell/foo-app

Il codice non deve trovarsi su github.com per poter essere compilato. Tuttavia, è consigliabile strutturare i moduli come se alla fine saranno pubblicati.

Capire cosa succede quando si cerca di ottenere un pacchetto

C'è un ottimo articolo qui che parla di cosa succede quando si tenta di ottenere un pacchetto o un modulo: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16 Discute dove è archiviato il pacchetto e lo farà aiutarti a capire perché potresti ricevere questo errore se stai già utilizzando i moduli Go.

Assicurarsi che la funzione importata sia stata esportata

Nota che se hai problemi ad accedere a una funzione da un altro file, devi assicurarti di aver esportato la tua funzione. Come descritto nel primo link che ho fornito, una funzione deve iniziare con una lettera maiuscola per essere esportata e resa disponibile per l'importazione in altri pacchetti.

Nomi delle directory

Un altro dettaglio critico (come menzionato nella risposta accettata) è che i nomi delle directory sono ciò che definisce i nomi dei pacchetti. (I nomi dei pacchetti devono corrispondere ai nomi delle loro directory.) Puoi vedere esempi di questo qui: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc With ciò detto, il file contenente il mainmetodo (ovvero il punto di ingresso dell'applicazione) è in qualche modo esente da questo requisito.

Ad esempio, ho avuto problemi con le mie importazioni durante l'utilizzo di una struttura come questa:

/my-app
├── go.mod
├── /src
   ├── main.go
   └── /utils
      └── utils.go

Non sono riuscito a importare il codice nel utilsmio mainpacchetto.

Tuttavia, una volta inserito main.gonella propria sottodirectory, come mostrato di seguito, le mie importazioni hanno funzionato perfettamente:

/my-app
├── go.mod
├── /src
   ├── /app
   |  └── main.go
   └── /utils
      └── utils.go

In questo esempio, il mio file go.mod è simile al seguente:

module git.mydomain.com/path/to/repo/my-app

go 1.14

Quando ho salvato main.go dopo aver aggiunto un riferimento a utils.MyFunction(), il mio IDE ha inserito automaticamente il riferimento al mio pacchetto in questo modo:

import "git.mydomain.com/path/to/repo/my-app/src/my-app"

(Sto usando VS Code con l'estensione Golang.)

Si noti che il percorso di importazione includeva la sottodirectory del pacchetto.

Trattare con un repository privato

Se il codice fa parte di un repository privato, è necessario eseguire un comando git per abilitare l'accesso. Altrimenti, puoi riscontrare altri errori Questo articolo menziona come farlo per i repository Github, BitBucket e GitLab privati: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repository-dfe795068db4 Questo problema è anche discusso qui: qual è il modo corretto di "andare a prendere" un repository privato?


-6

Hai provato ad aggiungere la directory assoluta di go al tuo 'percorso'?

export PATH=$PATH:/directory/to/go/

$ PATH non ha nulla a che fare con il tuo percorso per i pacchetti go.
csgeek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.