Хотя принятый ответ по-прежнему верен в отношении необходимости сопоставления каталогов с именами пакетов, вам действительно нужно перейти на использование модулей Go вместо использования GOPATH. Новые пользователи, столкнувшиеся с этой проблемой, могут быть сбиты с толку упоминаниями об использовании GOPATH (как и я), которые сейчас устарели. Итак, я постараюсь прояснить эту проблему и дать рекомендации, связанные с предотвращением этой проблемы при использовании модулей Go.
Если вы уже знакомы с модулями Go и столкнулись с этой проблемой, перейдите к моим более конкретным разделам ниже, в которых рассматриваются некоторые соглашения Go, которые легко упустить из виду или забыть.
В этом руководстве рассказывается о модулях Go: https://golang.org/doc/code.html
Организация проекта с помощью модулей Go
После перехода на модули Go, как упоминалось в этой статье, организуйте код проекта, как описано:
Репозиторий содержит один или несколько модулей. Модуль - это набор связанных пакетов Go, которые выпускаются вместе. Репозиторий Go обычно содержит только один модуль, расположенный в корне репозитория. Файл с именем go.mod объявляет путь к модулю: префикс пути импорта для всех пакетов в модуле. Модуль содержит пакеты в каталоге, содержащем его файл go.mod, а также подкаталоги этого каталога, вплоть до следующего подкаталога, содержащего другой файл go.mod (если есть).
Путь к каждому модулю не только служит префиксом пути импорта для его пакетов, но также указывает, где команда go должна искать его для его загрузки. Например, чтобы загрузить модуль golang.org/x/tools, команда go обращается к репозиторию, указанному https://golang.org/x/tools (подробнее описано здесь).
Путь импорта - это строка, используемая для импорта пакета. Путь импорта пакета - это путь к модулю, соединенный с его подкаталогом внутри модуля. Например, модуль github.com/google/go-cmp содержит пакет в каталоге cmp /. Путь импорта этого пакета - github.com/google/go-cmp/cmp. Пакеты в стандартной библиотеке не имеют префикса пути к модулю.
Вы можете инициализировать свой модуль следующим образом:
$ go mod init github.com/mitchell/foo-app
Ваш код не обязательно должен находиться на github.com для его сборки. Однако лучше всего структурировать модули так, как будто они будут опубликованы.
Понимание того, что происходит при попытке получить посылку
Здесь есть отличная статья, в которой рассказывается о том, что происходит, когда вы пытаетесь получить пакет или модуль: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
В нем обсуждается, где пакет хранится и будет поможет вам понять, почему вы можете получить эту ошибку, если вы уже используете модули Go.
Убедитесь, что импортированная функция была экспортирована
Обратите внимание: если у вас возникли проблемы с доступом к функции из другого файла, вам необходимо убедиться, что вы экспортировали свою функцию. Как описано в первой предоставленной мной ссылке, функция должна начинаться с заглавной буквы, чтобы ее можно было экспортировать и сделать доступной для импорта в другие пакеты.
Имена каталогов
Еще одна важная деталь (как упоминалось в принятом ответе) заключается в том, что имена каталогов определяют имена ваших пакетов. (Имена ваших пакетов должны совпадать с именами их каталогов.) Вы можете увидеть примеры этого здесь: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc
With при этом файл, содержащий ваш main
метод (т. е. точку входа вашего приложения), вроде как освобожден от этого требования.
Например, у меня были проблемы с импортом при использовании такой структуры:
/my-app
├── go.mod
├── /src
├── main.go
└── /utils
└── utils.go
Мне не удалось импортировать код в utils
свой main
пакет.
Однако, как только я поместил main.go
в отдельный подкаталог, как показано ниже, мой импорт работал нормально:
/my-app
├── go.mod
├── /src
├── /app
| └── main.go
└── /utils
└── utils.go
В этом примере мой файл go.mod выглядит так:
module git.mydomain.com/path/to/repo/my-app
go 1.14
Когда я сохранил main.go после добавления ссылки на utils.MyFunction()
, моя IDE автоматически вставила ссылку на мой пакет следующим образом:
import "git.mydomain.com/path/to/repo/my-app/src/my-app"
(Я использую VS Code с расширением Golang.)
Обратите внимание, что путь импорта включает подкаталог пакета.
Работа с частным репо
Если код является частью частного репо, вам необходимо запустить команду git, чтобы разрешить доступ. В противном случае вы можете столкнуться с другими ошибками. В этой статье упоминается, как это сделать для частных репозиториев Github, BitBucket и GitLab: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositories-dfe795068db4
Эта проблема также обсуждается здесь: Как правильно «получить» частный репозиторий?