Как импортировать локальные пакеты в go?

90

Я новичок и работаю над примером кода, который хочу локализовать.

В исходном main.goзаявлении импорта это было:

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

Теперь у меня есть commonи routersпакет в/home/me/go/src/myapp

Поэтому я преобразовал оператор импорта в:

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

Но когда я бегу, go install myappя получаю следующие ошибки:

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

Кроме того, когда я использую commonи routersвместо ./commonи ./routersв операторе импорта, я получаю:

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)

Как я могу это исправить?

Карлом
источник
5
Все операции импорта являются «локальными» независимо от пути импорта. См. «Как написать код Go» для подробного объяснения.
JimB
21
@JimB Не говоря уже о философских дебатах, меня беспокоит, как решить проблему, упомянутую выше.
Карлом
3
Я не пытаюсь сделать философское заявление, я буквально говорю, что весь импорт происходит в вашей локальной файловой системе; нет никакой разницы, происходят они из удаленного репо или нет. Не пытайтесь использовать относительные пути (иногда они работают, но не рекомендуется) и просмотрите документ «Как написать код Go», особенно раздел «Организация кода» .
JimB

Ответы:

63

Что ж, с проблемой разобрался. Обычно начальный путь Go для импорта$HOME/go/src

Поэтому мне просто нужно было добавить myappперед именами пакетов, то есть импорт должен быть:

import (
    "log"
    "net/http"
    "myapp/common"
    "myapp/routers"
)
Карлом
источник
3
использование имени проекта, например, myapp- плохая идея, например, если вы измените имя проекта, весь импорт будет неудачным
TomSawyer
7
Какая альтернатива? Go не рекомендует использовать относительный импорт.
Сэм Холмс
11
Конечно, если вы измените имя проекта, импорт не удастся. Название проекта меняется редко.
Дэмиен Рош
21
Что ж, с go1.11 вы можете использовать новую систему модулей. go mod init <module_name>а потом просто import "<module_name>/<pkg_name>".
крик
Как мы можем импортировать github.com/dgrijalva/jwt-go в наш файл .go? Моя папка jwt-go находится внутри src / github.com / dgrijalva
Маник Тхакур
30

Если вы используете Go 1.5, описанный выше, вы можете попробовать использовать функцию продажи . Это позволяет вам поместить локальный пакет в папку поставщика и импортировать его с более коротким путем. В вашем случае вы можете поместить свою общую папку и папку маршрутизаторов в папку поставщика, чтобы это было похоже на

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

и импортируйте его вот так

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

Это будет работать, потому что Go попытается найти ваш пакет, начиная с каталога vendor вашего проекта (если он имеет хотя бы один файл .go) вместо $ GOPATH / src.

К вашему сведению: вы можете сделать больше с поставщиком, потому что эта функция позволяет вам поместить «весь код вашей зависимости» для пакета в каталог вашего собственного проекта, чтобы он всегда мог получать одни и те же версии зависимостей для всех сборок. Это похоже на npm или pip в python, но вам нужно вручную скопировать свои зависимости в свой проект, или, если вы хотите упростить это, попробуйте поискать губернатора Даниэля Феофана

Чтобы узнать больше об этой функции, попробуйте найти здесь

Понимание и использование папки поставщика, Даниэль Феофанес

Понимание управления зависимостями в Go, Лукас Фернандес да Коста

Я надеюсь, что вы или кто-то другой найдете это полезным

аримаулана
источник
18

Пути импорта относятся к вашим переменным $GOPATHи $GOROOTпеременным среды. Например, со следующим $GOPATH:

GOPATH=/home/me/go

Пакеты, расположенные в /home/me/go/src/lib/commonи /home/me/go/src/lib/routersимпортируются соответственно как:

import (
    "lib/common"
    "lib/routers"
)
Wlredeye
источник
Да, первый пример был моей ошибкой.
wlredeye
Что вы имеете в виду под относительным путем, не поддерживаемым инструментами?
wlredeye
2
Вы не можете использовать go installпакеты, использующие относительный импорт.
JimB
Я думаю, что это недоразумение. Я имею в виду относительно GOPATH. Не просто родственник, как "../../mypackage"
wlredeye
Это относилось к той части, которую вы исправили при импорте относительно текущего каталога. Да, весь пользовательский импорт относится к файлам $GOPATH/src.
JimB
5

Локальный пакет - досадная проблема на ходу.

Для некоторых проектов в нашей компании мы решаем вообще не использовать подпакеты.

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

Все работает.

Для некоторых проектов мы используем подпакеты и импортируем локальные пакеты с полным путем:

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

Но если мы форкнем этот проект, то подпакеты все равно будут ссылаться на исходный.

Танксинфа
источник