Avatar ·

Go build: не может найти пакет, хотя GOPATH и модули настроены

Привет, коллеги! Я новичок в Go и уже второй день бьюсь над проблемой. Написал простую программу, которая использует внешний пакет для работы с JSON (например, `github.com/tidwall/gjson`). Я установил Go 1.22 на Ubuntu, создал папку `~/go_projects/myapp`, внутри — файл `main.go`. Вот мой код: ```go package main import ( "fmt" "github.com/tidwall/gjson" ) func main() { json := `{"name": "Alice", "age": 30}` value := gjson.Get(json, "name") fmt.Println(value.String()) } ``` Я выполнил `export GOPATH=$HOME/go` и `export PATH=$PATH:$GOPATH/bin`, затем запустил `go mod init myapp` в папке проекта. После этого попробовал `go build`, но получил ошибку: ``` build command-line-arguments: cannot find package "github.com/tidwall/gjson" in any of: /usr/local/go/src/github.com/tidwall/gjson (from $GOROOT) /home/user/go/src/github.com/tidwall/gjson (from $GOPATH) ``` Я пробовал `go get github.com/tidwall/gjson` — пишет, что команда устарела, и советует использовать `go mod tidy`. Запустил `go mod tidy` — он создал `go.mod` и `go.sum`, но ошибка сборки осталась. Что я делаю не так? GOPATH вроде бы правильный, модули инициализированы, но Go всё равно ищет пакет в старых путях. Помогите, пожалуйста, разобраться! <<>>

Проблема: смешение GOPATH-режима и модульного режима

Основная причина вашей ошибки — Go пытается работать в старом GOPATH-режиме, хотя вы используете модули. Это происходит потому, что проект находится вне стандартной GOPATH-структуры или переменная окружения GO111MODULE не настроена правильно.

Начиная с Go 1.16, модульный режим включён по умолчанию, но если ваш проект лежит внутри $GOPATH/src, Go может запутаться. Давайте пошагово исправим ситуацию.

Шаг 1: Проверьте расположение проекта

Убедитесь, что ваш проект НЕ находится внутри $GOPATH/src. Если он там — переместите его в любое другое место, например:

mv ~/go_projects/myapp ~/myapp
cd ~/myapp

Шаг 2: Удалите старые артефакты и переинициализируйте модуль

rm -rf go.mod go.sum
go mod init myapp

Шаг 3: Установите переменную GO111MODULE (на всякий случай)

export GO111MODULE=on

Добавьте эту строку в ~/.bashrc или ~/.zshrc для постоянного эффекта.

Шаг 4: Загрузите зависимости

go mod tidy

Эта команда прочитает ваш main.go, найдёт все импорты, скачает их в $GOPATH/pkg/mod и обновит go.mod и go.sum.

Шаг 5: Соберите проект

go build -o myapp

Если всё сделано правильно, ошибка исчезнет, и появится исполняемый файл myapp.

Почему это работает?

  • Модульный режим — Go использует файл go.mod для управления зависимостями, а не GOPATH/src.
  • go mod tidy автоматически загружает недостающие пакеты в кэш модулей ($GOPATH/pkg/mod), а не в src.
  • Если проект лежит внутри $GOPATH/src, Go может по ошибке включить GOPATH-режим, даже если go.mod существует.

Дополнительная проверка

Посмотрите содержимое go.mod после go mod tidy — там должны быть строки вида:

require github.com/tidwall/gjson v1.17.3

Если этого нет — значит, импорт в коде написан с ошибкой (например, лишний пробел или кавычки).

Что делать, если проблема осталась?

  1. Проверьте версию Go: go version — должна быть 1.16+.
  2. Убедитесь, что нет опечаток в импорте: "github.com/tidwall/gjson" (все буквы строчные).
  3. Попробуйте go env GOPATH и go env GO111MODULE — значение GO111MODULE должно быть on.

После этих шагов ваш код должен собираться без ошибок. Удачи!

<<>>

Альтернативный подход: используйте go work для многомодульных проектов

Если вы работаете с несколькими модулями (например, свой пакет и внешняя зависимость), удобно использовать go.work файлы. Это особенно актуально для Go 1.18+.

Создайте файл go.work в корневой директории (например, ~/myapp):

go 1.22

use (
    .
)

Затем выполните:

go work init
go mod tidy
go build

Когда это полезно?

  • Когда у вас есть локальные зависимости (например, ./helpers).
  • Когда вы хотите явно указать Go, где искать модули, игнорируя GOPATH.
  • Если go mod tidy не решает проблему, go work часто помогает "перезагрузить" контекст сборки.

Почему это работает?

go.work переопределяет поиск модулей: Go сначала смотрит в go.work, затем в go.mod, и только потом в GOPATH. Это гарантирует, что ваш проект будет собран в изолированном окружении, независимо от того, где он физически находится.

Попробуйте этот метод, если основной ответ не помог — он особенно эффективен при миграции со старых GOPATH-проектов на модули.