GOPATH и GOROOT: что куда ставить и почему это важно
Если вы только начинаете изучать Go, рано или поздно вы наткнётесь на магические аббревиатуры GOPATH и GOROOT. Вопрос «What should be the values of GOPATH and GOROOT?» — один из самых популярных на Stack Overflow, и это не случайно. Новички путаются, ставят их неправильно и получают странные ошибки при сборке проектов.
В этой статье мы на пальцах объясним, зачем нужны эти переменные, какие значения им присваивать по умолчанию, и как перейти на современный подход с go modules. Погнали!
Что такое GOROOT?
GOROOT — это путь к папке, в которую установлен сам компилятор Go. Внутри этой папки лежат стандартные пакеты (fmt, net, os и т.д.), а также бинарники go, gofmt и другие утилиты.
Большинству разработчиков не нужно явно задавать GOROOT. Если вы установили Go через официальный установщик или пакетный менеджер, компилятор сам знает, где находится.
Как проверить текущее значение GOROOT?
Откройте терминал и выполните:
go env GOROOT
Пример вывода на Linux:
/usr/local/go
На Windows (если установка была по умолчанию):
C:\Program Files\Go
Когда нужно менять GOROOT?
- Если вы перенесли папку с Go в другое место.
- Если у вас установлено несколько версий Go и вы хотите переключиться между ними.
- Если вы компилируете Go из исходников и установили его в нестандартную директорию.
Во всех остальных случаях оставьте GOROOT в покое — пусть Go сам о нём заботится.
Что такое GOPATH?
А вот GOPATH — куда более интересная переменная. Исторически Go требовал, чтобы весь ваш код лежал в одной рабочей области. Эта область и задавалась через GOPATH.
По умолчанию GOPATH указывает на:
- Linux/macOS:
$HOME/go - Windows:
%USERPROFILE%\go
Внутри этой папки стандартная структура:
go/
├── bin/ # скомпилированные бинарники
├── pkg/ # собранные объектные файлы и кэш
└── src/ # исходный код ваших проектов
├── github.com/
│ └── user/
│ └── myproject/
└── example.com/
└── myapp/
Как проверить текущее значение GOPATH?
go env GOPATH
Что должно быть в GOPATH и GOROOT? (Правильные значения)
Вот краткий ответ на главный вопрос:
| Переменная | Значение по умолчанию (Linux/macOS) | Значение по умолчанию (Windows) |
|---|---|---|
GOROOT |
/usr/local/go |
C:\Program Files\Go |
GOPATH |
$HOME/go |
%USERPROFILE%\go |
Важно: GOPATH и GOROOT должны быть разными папками. Никогда не ставьте их одинаковыми!
Типичные ошибки и как их исправить
Ошибка 1: «GOPATH not set» или «cannot find package»
Если вы используете старый подход (до версий 1.11-1.13), Go ищет пакеты внутри $GOPATH/src. Если вы положили проект в другое место, компилятор его не найдёт.
Решение:
- Либо переместите проект в
$GOPATH/src. - Либо (правильный путь!) перейдите на
go modules— это избавит вас от привязки кGOPATH.
Ошибка 2: GOROOT указывает на GOPATH
Никогда не делайте так:
export GOROOT=$HOME/go # НЕПРАВИЛЬНО!
export GOPATH=$HOME/go # теперь обе переменные совпадают
Это приведёт к тому, что Go попытается найти стандартные пакеты внутри вашей рабочей папки, а не там, где они реально установлены. Компилятор просто сломается.
Ошибка 3: Пути с пробелами (Windows)
Если ваш пользователь называется «John Doe», папка будет C:\Users\John Doe\go. Пробелы в путях могут вызывать странные ошибки при сборке. Лучше задать GOPATH вручную без пробелов, например:
set GOPATH=C:\GoWorkspace
Современный подход: Go Modules
Начиная с Go 1.11 и особенно с Go 1.16, модули стали стандартом. Теперь вам не обязательно держать проект внутри GOPATH/src.
Пример: вы хотите создать новый проект в папке /home/user/projects/myapp.
mkdir -p /home/user/projects/myapp
cd /home/user/projects/myapp
go mod init example.com/myapp
После этой команды в папке появится файл go.mod. Теперь вы можете писать код, импортировать сторонние библиотеки, и Go сам скачает их в $GOPATH/pkg/mod, а не в src.
Плюсы модулей:
- Не нужно думать о
GOPATHдля каждого проекта. - Фиксированные версии зависимостей.
- Возможность хранить проекты где угодно.
Пример кода: проверяем и задаём переменные
Напишем маленькую программу на Go, которая выводит текущие значения переменных окружения:
package main
import (
"fmt"
"os"
"runtime"
)
func main() {
goroot := os.Getenv("GOROOT")
gopath := os.Getenv("GOPATH")
fmt.Println("Операционная система:", runtime.GOOS)