Почему "go get" сломался и как это исправить?
Если вы когда-нибудь задавались вопросом "How can I install a package with go get?" — вы не одиноки. Этот вопрос набрал тысячи просмотров на Stack Overflow, и не зря. Раньше всё было просто: go get github.com/some/package — и библиотека у вас в $GOPATH/src. Но после выхода Go 1.16 всё изменилось. Теперь go get больше не устанавливает пакеты в привычном смысле. Вместо этого он только обновляет go.mod. А для установки бинарников появилась команда go install.
В этой статье мы разберёмся, что произошло, как теперь правильно устанавливать пакеты и зависимости, и почему новички так часто путаются. Поехали!
Краткая история: от GOPATH к модулям
До версии Go 1.11 весь код жил в GOPATH — специальной папке, где лежали все ваши проекты и сторонние пакеты. Команда go get скачивала исходники прямо туда. Это было удобно, но порождало проблемы с версиями: если два проекта требовали разные версии одной библиотеки — начинался ад.
С приходом Go modules (начиная с Go 1.11 и стабильно с 1.16) каждый проект получил свой go.mod — файл, где прописаны зависимости и их версии. Теперь go get работает иначе:
- Добавляет зависимость в
go.mod - Скачивает её в кеш (обычно
$GOPATH/pkg/mod) - Не создаёт бинарник в
$GOPATH/bin
Если вам нужно установить готовую программу (например, утилиту командной строки) — используйте go install.
Как работает go get сейчас: пошаговый разбор
Откройте терминал и создайте новый модуль:
mkdir myproject
cd myproject
go mod init myproject
Теперь хотим добавить, скажем, популярную библиотеку gorilla/mux для маршрутизации. Раньше мы бы написали:
go get github.com/gorilla/mux
И это сработает — библиотека скачается. Но посмотрите, что произошло:
- В
go.modпоявилась строка:require github.com/gorilla/mux v1.8.0 - В папке проекта появился
go.sum— файл с контрольными суммами для безопасности - Исходники библиотеки лежат в кеше, а не рядом с проектом
Теперь в вашем коде можно импортировать пакет:
package main
import (
"fmt"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
fmt.Println("Router created!")
}
Запускаем go run main.go — всё работает. Но если вы хотели получить бинарник (скомпилированную программу) — go get вам его не даст.
Установка бинарников: go install спешит на помощь
Допустим, вы нашли крутую утилиту на Go, например golangci-lint — линтер для кода. Чтобы установить её как команду в систему, раньше писали:
go get github.com/golangci/golangci-lint/cmd/golangci-lint
Сейчас это не сработает (выдаст предупреждение). Правильный способ:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Что произойдёт:
- Go скачает исходники утилиты
- Скомпилирует их
- Положит готовый бинарник в
$GOPATH/bin(или$GOBIN, если переменная задана)
Убедитесь, что $GOPATH/bin добавлен в PATH — иначе команда не будет доступна. Проверить можно так:
echo $GOPATH
# обычно /home/user/go
ls ~/go/bin/
Если там есть ваш бинарник — всё ок.
Типичные ошибки новичков (и как их избежать)
На Stack Overflow чаще всего спрашивают про эти грабли:
- "go get не создаёт папку src" — да, теперь всё иначе. Забудьте про
$GOPATH/srcдля своих проектов. Используйте модули. - "Я написал go get, а пакет не импортируется" — проверьте, что вы выполнили команду внутри папки с
go.mod. Без модуляgo getможет не сработать. - "Не могу найти установленную программу" — проверьте
PATH. Добавьтеexport PATH=$PATH:$(go env GOPATH)/binв.bashrcили.zshrc. - "Хочу установить конкретную версию" — используйте
go get package@v1.2.3для зависимостей илиgo install package@v1.2.3для бинарников.
Практический пример: своя утилита из GitHub
Представьте, что вы нашли полезный пакет github.com/spf13/cobra — это фреймворк для создания CLI-приложений. Вы хотите не использовать его как библиотеку, а установить готовую программу cobra (генератор проектов).
Порядок действий:
- Откройте терминал (не обязательно быть внутри проекта)
- Выполните:
go install github.com/spf13/cobra-cli@latest - Проверьте:
cobra-cli --help
Готово! Вы установили утилиту глобально. Если хотите обновиться — просто повторите команду. Если нужно удалить — удалите файл из $GOPATH/bin.
А что если проект без модулей?
Бывает, что вы работаете со старым кодом, где нет go.mod. В этом случае go get всё ещё может работать в режиме совместимости, но лучше всё-таки добавить модуль. Сделайте:
go mod init myoldproject
go mod tidy
Команда go mod tidy подтянет все зависимости, которые реально используются в коде, и запишет их в go.mod. Это безопасно и чинит большинство проблем.
Советы для продуктивной работы
Чтобы не путаться, запомните три правила:
- Хотите добавить