Экосистема и инструментарий: Go Modules и компиляция в бинарный файл

Мы уже обсудили, что Go придерживается философии явности и простоты. Теперь посмотрим, как эти принципы работают при создании проектов. Если в React вы привыкли к гигабайтам в node_modules и сложным конфигам Webpack или Vite, то в Go вас ждет радикальный минимализм.

От node_modules к Go Modules

В Node.js зависимости часто превращаются в «ад матрешек»: библиотеки тянут друг друга и хранятся прямо в папке проекта. В Go всё иначе. Центральное понятие здесь — Go Modules. Это система, которая делает сборку предсказуемой и избавляет от локального мусора.

Вместо package.json мы используем go.mod. Это манифест модуля, где указано его имя, версия Go и список библиотек.

Три главных отличия:

  1. Чистые папки. В проекте нет кода библиотек. Все зависимости скачиваются один раз в единый глобальный кэш системы.
  2. Безопасность через go.sum. Файл go.sum хранит контрольные суммы (хеши) всех зависимостей. Это гарантия того, что код на вашей машине и на сервере будет идентичным до последнего байта.
  3. Единый Toolchain. В современном Go (1.22+) файл go.mod фиксирует версию компилятора. Это исключает баги из-за разницы версий языка у разработчиков.

Как соотносится структура Go-проекта с привычным React-приложением, можно увидеть на Схеме 1.

Управление зависимостями

Чтобы начать проект, инициализируйте модуль. В Go принято называть модули по пути в репозитории:

go mod init github.com/username/awesome-api

После этого появится go.mod. Вы можете добавлять библиотеки через go get, но есть способ лучше — go mod tidy. Эта команда сканирует ваш код, находит импорты, скачивает нужное и удаляет лишнее.

Сравните манифесты. Вариант Go выглядит гораздо лаконичнее:

Манифест в Go (go.mod):

module github.com/myuser/awesome-api

go 1.22.0

require (
    github.com/google/uuid v1.6.0
    github.com/lib/pq v1.10.9 // indirect
)

Манифест в Node.js (package.json):

{
  "name": "awesome-api",
  "version": "1.0.0",
  "dependencies": {
    "uuid": "^9.0.0"
  }
}

На заметку: В Go нет секции scripts. Для автоматизации (запуск тестов, линтеров) бэкенд-разработчики обычно используют Makefile или Taskfile.

Магия Static Binary

В React результатом сборки становится бандл из JS и CSS, которому нужен браузер или Node.js. В Go команда go build создает Static Binary.

Это один исполняемый файл, который уже содержит:

  • Ваш скомпилированный код.
  • Все внешние библиотеки.
  • Runtime самого Go и сборщик мусора (Garbage Collector).

Такой файл не требует установки Go на сервере. Просто копируете его и запускаете. Благодаря этому Docker-образы для Go весят 15–30 МБ против 500 МБ у Node.js 🪶

Кросс-компиляция через Toolchain

Встроенный Toolchain позволяет собирать приложение под любую ОС прямо с вашего рабочего места. Если вы пишете код на macOS, а сервер работает на Linux, достаточно двух переменных окружения:

# Сборка под Linux (x86-64) с любого компьютера
GOOS=linux GOARCH=amd64 go build -o my_app_linux main.go

Вы всегда точно знаете, какой артефакт попадет в продакшен. Никаких сюрпризов при деплое.

Организация кода

В Go-сообществе приняты стандарты структуры папок, чтобы избежать хаоса в микросервисах:

  • cmd/ — точки входа в приложение (файлы с функцией main).
  • internal/ — приватный код, который нельзя импортировать в другие проекты (инкапсуляция на уровне файловой системы).
  • pkg/ — публичные библиотеки, которыми вы готовы поделиться с миром.

Мы разобрались, как управлять проектом и собирать готовый продукт. Теперь пора изучить «кирпичики», из которых строится логика. В следующей теме мы перейдем к фундаменту: узнаем, как Go работает с числами и почему строки здесь устроены совсем не так, как в TypeScript.