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 main
mé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 utils
meu main
pacote.
No entanto, depois que eu coloquei main.go
em 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?