Перехід: "Неможливо знайти пакет" (навіть якщо GOPATH встановлений)


139

Незважаючи на те, що я GOPATHналаштований належним чином, я все ще не можу "побудувати" або "запустити", щоб знайти власні пакети. Що я роблю неправильно?

$ echo $GOROOT
/usr/local/go

$ echo $GOPATH
/home/mitchell/go

$ cat ~/main.go
package main
import "foobar"
func main() { }

$ cat /home/mitchell/go/src/foobar.go
package foobar

$ go build main.go
main.go:3:8: import "foobar": cannot find package

З тією ж проблемою я зустрічаюсь, коли йду отримувати github.com/adonovan/gopl.io/tree/master/ch1/helloworld Причиною цього є те, що у нього немає файлу імені helloworld.go. перейдіть до роботи, узгоджуючи назву пакета та ім'я файлу.
keniee van

Можливо, вам потрібно оновити Go. У мене була подібна проблема, коли у мене був існуючий код, використовуючи go.mod для визначення модуля. На тестовій машині я завантажив код і намагався його скомпілювати, але Go давав мені всілякі помилки, пов’язані з GOPATH, і неможливо знайти модулі. Це була версія версії 1.7. Як тільки я модернізував Go, це працювало без проблем.
KyferEz

Введіть це термінал для актуального пояснення$ go help gopath
A1rPun

Відповіді:


162

Це не працює, оскільки ваш foobar.goвихідний файл не знаходиться в каталозі, який називається foobar. go buildі go installспробуйте відповідати каталогам, а не вихідним файлам.

  1. Встановіть $GOPATHдійсну директорію, наприкладexport GOPATH="$HOME/go"
  2. Переїзд foobar.goдо $GOPATH/src/foobar/foobar.goбудівництва повинен працювати добре.

Додаткові рекомендовані кроки:

  1. Додайте $GOPATH/binдо свого $PATH:PATH="$GOPATH/bin:$PATH"
  2. Перехід main.goдо підпапки $GOPATH/src, наприклад$GOPATH/src/test
  3. go install testТепер слід створити виконуваний файл, $GOPATH/binякий можна викликати, ввівши testу свій термінал.

1
Це не помилка? Мій GOPATH=/usr/local/go-pkgs, тому Го шукає /usr/local/go-pkgs/src/<package-name>джерело, але go getвкладає його /usr/local/go-pkgs/src/gopkg.in/<package-name>. Чому я повинен вручну переміщувати всі свої пакунки після встановлення? Це просто нерозумно.
Іосія

3
go getзазвичай ставить пакунки, $GOPATH/src/тому якщо ви зателефонуєте, go get domain.com/path/to/packageвін закінчиться в $GOPATH/src/domain.com/path/to/package. Я думаю, ви намагаєтеся отримати пакет з gopkg.in? Якщо так, то абсолютно призначена поведінка, і вам слід просто імпортувати їх з повним ім'ям; наприклад, import "gopkg.in/yaml.v1"як це також описано в документах .
фасмат

1
А-а-а, бачу. Дякую, що розвіяв моє незнання.
josiah

10

Edit: так як ви мали в виду GOPATH см fasmat «сек відповідь (upvoted)

Як було сказано в " Як змусити перейти знайти свій пакет? ", Потрібно помістити пакунок xxxу каталог xxx.

Дивіться специфікацію мови Go :

package math

Набір файлів, що мають спільну PackageNameформу, реалізують пакет.
Реалізація може зажадати, щоб усі вихідні файли для пакета заселяли один і той же каталог.

Організація Кодексу згадує:

При створенні програми , яка імпортує пакет « widget» то goкоманда переглядає src/pkg/widgetвсередині кореня Go, а потім, якщо вихідний пакет не знайдений, він шукає src/widgetвсередині кожної робочої області в порядку.

("робоча область" - це запис у вашому GOPATH: ця змінна може посилатися на декілька шляхів для вашого " src, bin, pkg")


(Оригінальна відповідь)

Ви також повинні встановити GOPATH~ / go, а не GOROOT, як показано у " Як написати Go Code ".

Шлях Go використовується для вирішення операторів імпорту. Він реалізований та задокументований у пакеті go / build.

У GOPATHсписках змінних оточення місця шукати Go коду.
У Unix значення є розділеною двокрапкою.
У Windows значення є розділеною комою крапкою з комою.
На Плані 9 значенням є список.

Це відрізняється від GOROOT:

Бінарні дистрибутиви Go припускають, що вони будуть встановлені в /usr/local/go(або c:\Goпід Windows), але їх можна встановити в іншому місці.
Якщо ви це зробите, вам потрібно буде встановити GOROOTзмінну оточення до цієї директорії при використанні інструментів Go.


4
Також є короткий вступ до налаштування GOPATH
Ульф Холм Нільсен

1
Вибачте, я редагував оригінальне запитання. Скрізь, де я говорив GOROOT, я мав на увазі GOPATH.
MitchellSalad

3

TL; DR: Дотримуйтесь конвенцій Go! (урок засвоїв складний шлях), перевірте наявність старих версій go та видаліть їх. Встановити останню.

Для мене рішення було іншим. Я працював на спільному сервері Linux і після перевірки моїх GOPATHта інших змінних оточення кілька разів все ще не працював. У мене виникло кілька помилок, серед яких "Неможливо знайти пакунок" та "Нерозпізнаний шлях імпорту". Після спроби перевстановити це рішення за інструкціями на golang.org (включаючи частину для видалення ) все-таки виникли проблеми.

Знадобився деякий час, щоб зрозуміти, що є ще стара версія, яку не було видалено (запущена go versionпотім which goзнову ... DAHH), яка привернула мене до цього питання і остаточно вирішила.


2

Хоча прийнята відповідь все ще правильна щодо необхідності узгодження каталогів з іменами пакетів, вам дійсно потрібно перейти до використання модулів 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 Ця проблема також обговорюється тут: Який правильний спосіб "дістати" приватне сховище?


-6

Ви спробували додати абсолютну директорію переходу на свій «шлях»?

export PATH=$PATH:/directory/to/go/

$ PATH не має нічого спільного з вашим шляхом для пакетів go.
csgeek
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.