Пакеты, тестирование, файлы и JSON

Собственные пакеты: структура папок, exported и unexported имена

Содержание курса

До этого момента весь код жил в одном файле или в одной папке с пакетом main. Как только проект растёт — появляются вспомогательные функции, которые хочется переиспользовать — нужна другая структура. Go решает это очень конкретно: одна папка = один пакет.

Структура папок модуля и объявление пакетов main и mathutil

Создадим папку проекта и инициализируем модуль:

mkdir myapp && cd myapp
go mod init example.com/myapp

Команда go mod init не создаёт никаких вложенных папок с именем модуля — она просто записывает module path в файл go.mod текущего каталога. Физическая структура на диске выглядит так:

myapp/
├── go.mod
├── main.go
└── mathutil/
    └── mathutil.go

А содержимое go.mod — вот так:

module example.com/myapp

go 1.21

example.com/myapp — это module path: строка-идентификатор модуля, которую Go использует при импорте пакетов. Она не обязана совпадать с именем папки на диске; папка называется myapp, а module path — example.com/myapp.

Файл main.go начинается с package main — это точка входа. Файл mathutil/mathutil.go начинается с package mathutil. Это всё, что требуется от каждого файла: объявить, к какому пакету он принадлежит.

Главное правило: все .go-файлы в одной папке должны объявлять одно и то же имя пакета. Попытка смешать package mathutil и package util в одной папке приведёт к ошибке компиляции. Компилятор считает папку единицей: он компилирует всё содержимое сразу и требует единого package-объявления.

Имя папки и имя пакета принято делать одинаковыми — mathutil/ содержит package mathutil. Технически компилятор не требует этого совпадения, но весь инструментарий Go (включая go doc и большинство IDE) рассчитывает именно на такое соответствие.

Если хочется добавить ещё одну группу функций — создаём ещё одну подпапку со своим .go-файлом и своим package-объявлением. Глубина вложенности не ограничена, но каждая папка всё равно остаётся одним пакетом.