Хоча прийнята відповідь все ще правильна щодо необхідності узгодження каталогів з іменами пакетів, вам дійсно потрібно перейти до використання модулів 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 з розширенням Golang.)
Зауважте, що шлях імпорту містив підкаталог до пакету.
Справа з приватним репо
Якщо код є частиною приватного репо, вам потрібно виконати команду git, щоб дозволити доступ. В іншому випадку ви можете зіткнутися з іншими помилками У цій статті йдеться про те, як це зробити для приватних репортажів Github, BitBucket та GitLab: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositories-dfe795068db4
Ця проблема також обговорюється тут: Який правильний спосіб "дістати" приватне сховище?