Vá construir: "Não foi possível encontrar o pacote" (mesmo que GOPATH esteja definido)

139

Mesmo que eu tenha GOPATHdefinido corretamente, ainda não consigo "ir construir" ou "ir correr" para encontrar meus próprios pacotes. O que estou fazendo de errado?

$ 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
MitchellSalad
fonte
Encontro o mesmo problema quando for buscar github.com/adonovan/gopl.io/tree/master/ch1/helloworld O motivo deve ser que não há um arquivo com o nome helloworld.go. vá buscar obras combinando o nome e o nome do arquivo do pacote.
van keniee
Também pode ser que você precise atualizar o Go. Eu tive um problema semelhante em que eu tinha código existente usando go.mod para definir um módulo. Em uma máquina de teste, eu havia baixado o código e estava tentando compilá-lo, mas o Go estava me dando todos os tipos de erros relacionados ao GOPATH e não conseguia encontrar módulos. Foi a versão 1.7 do Go. Assim que eu atualizei o Go, ele funcionou sem problemas.
KyferEz
Digite este é terminal para uma explicação up-to-date$ go help gopath
A1rPun

Respostas:

162

Não funciona porque seu foobar.goarquivo de origem não está em um diretório chamado foobar. go builde go installtente combinar diretórios, não arquivos de origem.

  1. Defina $GOPATHpara um diretório válido, por exemploexport GOPATH="$HOME/go"
  2. Mover foobar.gopara $GOPATH/src/foobar/foobar.goe construir deve funcionar muito bem.

Etapas adicionais recomendadas:

  1. Adicione $GOPATH/binao seu $PATH:PATH="$GOPATH/bin:$PATH"
  2. Mover main.gopara uma subpasta de $GOPATH/src, por exemplo,$GOPATH/src/test
  3. go install testAgora, você deve criar um executável no $GOPATH/binqual possa ser chamado digitando testseu terminal.
fasmat
fonte
1
Isso não é um bug? Meu GOPATH=/usr/local/go-pkgs, então o Go procura /usr/local/go-pkgs/src/<package-name>a fonte, mas a go getcoloca /usr/local/go-pkgs/src/gopkg.in/<package-name>. Por que eu devo mover manualmente todos os meus pacotes após a instalação? Isso é bobagem.
josiah
3
go getnormalmente coloca pacotes, $GOPATH/src/então, se você ligar, go get domain.com/path/to/packageele terminará $GOPATH/src/domain.com/path/to/package. Eu acho que você tenta buscar um pacote gopkg.in? Nesse caso, esse é o comportamento pretendido e você deve apenas importá-los com o nome completo; por exemplo, import "gopkg.in/yaml.v1"como também descrito nos documentos .
fasmat 17/09/2015
1
Ahhhh, entendo. Obrigado por dissipar minha ignorância.
josiah
10

Edit: já que você significou GOPATH, consulte fasmat 's resposta (upvoted)

Como mencionado em " Como faço para encontrar meu pacote? ", Você precisa colocar um pacote xxxem um diretório xxx.

Veja a especificação do idioma Go :

package math

Um conjunto de arquivos que compartilham da mesma PackageNameforma a implementação de um pacote.
Uma implementação pode exigir que todos os arquivos de origem de um pacote habitem o mesmo diretório.

A organização do Código menciona:

Ao criar um programa que importa o pacote " widget", o gocomando procura src/pkg/widgetdentro da raiz Go e, se a fonte do pacote não for encontrada, ele procura src/widgetdentro de cada espaço de trabalho em ordem.

(um "espaço de trabalho" é uma entrada de caminho no seu GOPATH: essa variável pode fazer referência a vários caminhos para o seu ' src, bin, pkg')


(Resposta original)

Você também deve definir GOPATHcomo ~ / go, não GOROOT, conforme ilustrado em " Como escrever o código Go ".

O caminho Ir é usado para resolver instruções de importação. É implementado e documentado no pacote go / build.

A GOPATHvariável de ambiente lista lugares para procurar o código Go.
No Unix, o valor é uma sequência separada por dois pontos.
No Windows, o valor é uma sequência separada por ponto e vírgula.
No plano 9, o valor é uma lista.

Isso é diferente de GOROOT:

As distribuições binárias Go assumem que elas serão instaladas no /usr/local/go(ou c:\Gono Windows), mas é possível instalá-las em um local diferente.
Se você fizer isso, precisará definir a GOROOTvariável de ambiente para esse diretório ao usar as ferramentas Ir.

VonC
fonte
4
Há também uma breve introdução em vídeo sobre como configurar o GOPATH
Ulf Holm Nielsen
1
Desculpe, editei a pergunta original. Em todos os lugares que eu disse GOROOT, eu quis dizer GOPATH.
MitchellSalad
3

TL; DR: Siga as convenções do Go! (lição aprendida da maneira mais difícil), verifique as versões antigas e remova -as. Instale mais recente.

Para mim, a solução foi diferente. Trabalhei em um servidor Linux compartilhado e depois de verificar minhas GOPATHe outras variáveis ​​de ambiente várias vezes, ele ainda não funcionou. Encontrei vários erros, incluindo 'Não é possível encontrar o pacote' e 'Caminho de importação não reconhecido'. Depois de tentar reinstalar com esta solução, as instruções no golang.org (incluindo a parte de desinstalação ) ainda encontraram problemas.

Levei algum tempo para perceber que ainda há uma versão antiga que não tenha sido desinstalado (em execução go version, em seguida, which gonovamente ... DAHH) que me levou a esta questão e, finalmente, resolvido.

Moshisho
fonte
2

Embora a resposta aceita ainda esteja correta sobre a necessidade de corresponder diretórios com nomes de pacotes, você realmente precisa migrar para o uso de módulos Go em vez de usar GOPATH. Os novos usuários que encontrarem esse problema podem ficar confusos sobre as menções ao uso do GOPATH (como eu estava), que agora estão desatualizadas. Portanto, tentarei esclarecer esse problema e fornecer orientações associadas à prevenção desse problema ao usar os módulos Go.

Se você já conhece os módulos Go e está enfrentando esse problema, pule para as seções mais específicas abaixo, que abrangem algumas das convenções Go que são fáceis de ignorar ou esquecer.

Este guia ensina sobre os módulos Go: https://golang.org/doc/code.html

Organização do projeto com módulos Go

Depois de migrar para os módulos Go, conforme mencionado nesse artigo, organize o código do projeto conforme descrito:

Um repositório contém um ou mais módulos. Um módulo é uma coleção de pacotes Go relacionados que são liberados juntos. Um repositório Go normalmente contém apenas um módulo, localizado na raiz do repositório. Um arquivo chamado go.mod declara o caminho do módulo: o prefixo do caminho de importação para todos os pacotes dentro do módulo. O módulo contém os pacotes no diretório que contém seu arquivo go.mod, bem como os subdiretórios desse diretório, até o próximo subdiretório que contém outro arquivo go.mod (se houver).

O caminho de cada módulo não serve apenas como prefixo do caminho de importação para seus pacotes, mas também indica onde o comando go deve procurar baixá-lo. Por exemplo, para fazer o download do módulo golang.org/x/tools, o comando go consultaria o repositório indicado por https://golang.org/x/tools (descrito mais aqui).

Um caminho de importação é uma sequência usada para importar um pacote. O caminho de importação de um pacote é o caminho do módulo associado ao seu subdiretório no módulo. Por exemplo, o módulo github.com/google/go-cmp contém um pacote no diretório cmp /. O caminho de importação desse pacote é github.com/google/go-cmp/cmp. Pacotes na biblioteca padrão não têm um prefixo de caminho do módulo.

Você pode inicializar seu módulo assim:

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

Seu código não precisa estar localizado no github.com para que seja criado. No entanto, é uma boa prática estruturar seus módulos como se eles fossem publicados.

Entendendo o que acontece ao tentar obter um pacote

Há um ótimo artigo aqui que fala sobre o que acontece quando você tenta obter um pacote ou módulo: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16 Ele discute onde o pacote está armazenado e será ajudá-lo a entender por que você pode estar recebendo esse erro se já estiver usando os módulos Go.

Verifique se a função importada foi exportada

Observe que, se estiver com problemas para acessar uma função de outro arquivo, verifique se você exportou sua função. Conforme descrito no primeiro link que forneci, uma função deve começar com uma letra maiúscula para ser exportada e disponibilizada para importação em outros pacotes.

Nomes de diretórios

Outro detalhe crítico (como mencionado na resposta aceita) é que os nomes dos diretórios são os que definem os nomes dos seus pacotes. (Seus nomes de pacotes precisa combinar seus nomes de diretórios.) Você pode ver exemplos disso aqui: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc Com Dito isto, o arquivo que contém seu mainmétodo (ou seja, o ponto de entrada do seu aplicativo) está meio isento desse requisito.

Como exemplo, tive problemas com minhas importações ao usar uma estrutura como esta:

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

Não foi possível importar o código no utilsmeu mainpacote.

No entanto, depois que eu coloquei main.goem seu próprio subdiretório, como mostrado abaixo, minhas importações funcionaram muito bem:

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

Nesse exemplo, meu arquivo go.mod se parece com o seguinte:

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

go 1.14

Quando salvei o main.go após adicionar uma referência a utils.MyFunction(), meu IDE puxou automaticamente a referência ao meu pacote assim:

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

(Estou usando o VS Code com a extensão Golang.)

Observe que o caminho de importação incluiu o subdiretório no pacote.

Lidar com um repo privado

Se o código fizer parte de um repositório particular, você precisará executar um comando git para ativar o acesso. Caso contrário, você poderá encontrar outros erros. Este artigo menciona como fazer isso para repositórios particulares do Github, BitBucket e GitLab: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositories-dfe795068db4 Este problema também é discutido aqui: Qual é a maneira correta de "obter" um repositório privado?

devinbost
fonte
-6

Você já tentou adicionar o diretório absoluto de ir para o seu 'caminho'?

export PATH=$PATH:/directory/to/go/
RobEdouard
fonte
o $ PATH não tem nada a ver com o seu caminho para os pacotes go.
csgeek 7/04