Como importar pacotes locais em go?

101

Estou trabalhando em um código de exemplo que desejo localizar.

Na main.godeclaração de importação original era:

 import (
    "log"
    "net/http"
    "github.com/foo/bar/myapp/common"
    "github.com/foo/bar/myapp/routers"
)

Agora eu tenho commone routerspacote em/home/me/go/src/myapp

Então, converti a instrução import para:

import (
    "log"
    "net/http"
    "./common"
    "./routers"
)

Mas quando eu corro go install myapp, recebo estes erros:

can't load package: /home/me/go/src/myapp/main.go:7:3: local import "./common" in non-local package

Além disso, quando uso commone em routersvez de ./commone ./routersna instrução de importação, obtenho:

myapp/main.go:7:3: cannot find package "common" in any of:
    /usr/local/go/src/common (from $GOROOT)
    /home/me/go/src/common (from $GOPATH)
myapp/main.go:8:2: cannot find package "routers" in any of:
    /usr/local/go/src/routers (from $GOROOT)
    /home/me/go/src/routers (from $GOPATH)

Como posso consertar isso?

Karlom
fonte
5
Todas as importações são "locais", independentemente do caminho de importação. Consulte "Como escrever código Go" para uma explicação detalhada.
JimB de
24
@JimB deixando de lado os debates filosóficos, o que me preocupa é como resolver o problema mencionado acima.
Karlom
3
Não estou tentando fazer uma declaração filosófica, estou literalmente dizendo que todas as importações acontecem em seu sistema de arquivos local; nunca há diferença se eles se originam de um repo remoto ou não. Não tente usar caminhos relativos (eles funcionam às vezes, mas são desencorajados) e vá até o documento "Como escrever código Go", especificamente a seção sobre "Organização do código" .
JimB de

Respostas:

70

Bem, eu descobri o problema. Basicamente, o caminho inicial do Go para importação é$HOME/go/src

Então, eu só precisava adicionar myappna frente dos nomes dos pacotes, ou seja, a importação deveria ser:

import (
    "log"
    "net/http"
    "myapp/common"
    "myapp/routers"
)
Karlom
fonte
4
usar o nome do projeto como myappé uma má ideia, por exemplo, se você alterar o nome do projeto, toda a importação
falhará
9
Qual é a alternativa? Go não recomenda que você use importações relativas.
Sam Holmes
12
É claro que todas as importações falharão se você alterar o nome do projeto. O nome do projeto raramente muda.
Damien Roche
23
Bem, a partir de go1.11 você pode usar o novo sistema de módulos. go mod init <module_name>e então apenas import "<module_name>/<pkg_name>".
grito de
Como podemos importar github.com/dgrijalva/jwt-go em nosso arquivo .go? Minha pasta jwt-go está dentro de src / github.com / dgrijalva
Manik Thakur
34

Se estiver usando o Go 1.5 acima, você pode tentar usar o recurso de venda . Ele permite que você coloque seu pacote local na pasta do fornecedor e importe-o com um caminho mais curto. No seu caso, você pode colocar sua pasta comum e de roteadores dentro da pasta vendor para que seja como

myapp/
--vendor/
----common/
----routers/
------middleware/
--main.go

e importe assim

import (
    "common"
    "routers"
    "routers/middleware"
)

Isso funcionará porque Go tentará pesquisar seu pacote começando no diretório do fornecedor do seu projeto (se houver pelo menos um arquivo .go) em vez de $ GOPATH / src.

Para sua informação: você pode fazer mais com o fornecedor, porque este recurso permite que você coloque "todo o código de sua dependência" para um pacote dentro do diretório do seu próprio projeto, de forma que ele possa sempre obter as mesmas versões de dependências para todas as compilações. É como npm ou pip em python, mas você precisa copiar manualmente suas dependências para seu projeto ou, se quiser tornar mais fácil, tente procurar o governador de Daniel Theophanes

Para saber mais sobre esse recurso, tente procurar aqui

Compreendendo e usando a pasta de fornecedores por Daniel Theophanes

Noções básicas sobre Go Dependency Management por Lucas Fernandes da Costa

Espero que você ou outra pessoa o considere útil

arimaulana
fonte
19

Importação caminhos são relativos aos seus $GOPATHe $GOROOTvariáveis de ambiente. Por exemplo, com o seguinte $GOPATH:

GOPATH=/home/me/go

Pacotes localizados em /home/me/go/src/lib/commone /home/me/go/src/lib/routerssão importados respectivamente como:

import (
    "lib/common"
    "lib/routers"
)
wlredeye
fonte
Sim, o primeiro exemplo foi meu erro.
wlredeye
O que você quer dizer com caminho relativo não suportado pelo ferramental?
wlredeye
2
Você não pode go installpacotes que usam importações relativas.
JimB de
Eu acho que é um mal-entendido aqui. Quero dizer em relação ao GOPATH. Não apenas relativo como "../../mypackage"
wlredeye
Isso foi em referência à parte que você corrigiu sobre a importação em relação ao diretório atual. Sim, todas as importações de usuários são relativas a $GOPATH/src.
JimB de
5

O pacote local é um problema irritante em go.

Para alguns projetos em nossa empresa, decidimos não usar subpacotes.

  • $ glide install
  • $ go get
  • $ go install

Todo o trabalho.

Para alguns projetos, usamos subpacotes e importamos pacotes locais com o caminho completo:

import "xxxx.gitlab.xx/xxgroup/xxproject/xxsubpackage

Mas se bifurcarmos este projeto, os subpacotes ainda se referem ao original.

tangxinfa
fonte