Если JS/TS это гибкий асинхронный клей для веба на одном потоке, то Go это строгий инструмент для облака с честным параллелизмом.
Главная проблема новичка сейчас это старые учебники. Классический «Effective Go» писали в 2009-м, там нет ни модулей, ни дженериков. Учить по нему Go всё равно что учить JS по учебникам времен ES3.
Здесь не будет истории. Это гайд по современному Go (1.25+), который использует твой опыт в JS/TS, чтобы ты начал писать рабочий код, а не копался в легаси.
Главные отличия парадигм: Что вам нужно забыть
От асинхронности к параллелизму. В Node.js ваш главный враг блокировка цикла событий. Вы используете
async/await, чтобы отпустить поток во время ожидания I/O. В Go, благодаря легким горутинам, блокировка это нормально. Блокирующий вызов (например, чтение из базы данных) блокирует только текущую горутину, а не весь поток ОС, что делает код линейным и читаемым.От экосистемы к стандартной библиотеке. В мире JS/TS вы полагаетесь на npm для всего: веб-сервер, тестирование и даже базовые утилиты. Это минимальное ядро, максимальная экосистема. Go придерживается философии батарейки в комплекте. Производственный веб-сервер, JSON-парсер, фреймворк для тестирования и HTTP-клиент встроены в стандартную библиотеку.
От
classкstruct. В Go нет классов и нет наследования. Вместо этого вы используете структуры для данных и композицию (встраивание) для их объединения.От
try…catchкif err!= nil. В Go нет исключений. Функции, которые могут завершиться неудачно, просто возвращают ошибку как последнее значение. Вы должны явно проверять ее, а не ловить неявно.
Что нового и актуального (Go 1.18 - 1.25)
За последние несколько лет Go претерпел стратегические изменения, которые значительно снизили барьер входа для разработчиков из других языков, таких как TypeScript.
Дженерики (Go 1.18+). Самое большое изменение в истории языка. Это сделало язык гораздо более привычным для TS-разработчиков, которые ожидают
Array<T> и Map<K, V>.Исправление семантики цикла
for(Go 1.22+): Go исправил давнюю ловушку для новичков с захватом переменных в замыканиях. Эта проблема была идентична проблеме var в циклах JavaScript, которая была решена с помощью let. Теперь Go ведет себя так, как вы ожидаете.Итераторы (Go 1.23+). Введен новый, более эффективный способ итерации по пользовательским коллекциям с использованием range.
Новый
encoding/json/v2(Go 1.25) решает давние проблемы с JSON, которые часто приводили к багам на фронтенде, например, nil-слайсы теперь кодируются как ``, а не null.Структурированное логгирование (slog). В стандартную библиотеку добавлен новый, мощный пакет slog для современного JSON-логгирования.
Настройка и рабочий процесс
Первое, что нужно забыть, это GOPATH. В прошлом Go требовал, чтобы весь ваш код находился в одной глобальной директории $GOPATH. Эта эра закончилась. Начиная с Go 1.14, Модули Go (go.mod) являются стандартом. Теперь вы можете создавать проект в любой папке, точно так же, как вы это делаете с npm init.
go mod init(npm init): Эта команда создает файл go.mod.go.mod(package.json): Это центральный файл вашего проекта. Он определяет имя вашего модуля (например, github.com/my-user/my-project) и его прямые зависимости (секция require).go.sum(package-lock.json / yarn.lock): Этот файл генерируется автоматически. Он содержит контрольные суммы всех зависимостей (прямых и транзитивных) для обеспечения целостности и воспроизводимости сборок. В отличие от package-lock.json, он не блокирует версии, а гарантирует, что содержимое загруженных модулей не было подделано. Всегда коммитьте go.sum в свой репозиторий.Где
node_modules? Его нет.
В JS-проекте npm install создает локальную папку node_modules, которая может занимать гигабайты. В Go этого нет. Go загружает зависимости в единый глобальный кеш (обычно в $GOPATH/pkg/mod). Все ваши проекты на диске остаются маленькими и ссылаются на этот кеш. Это не только экономит место, но и делает CI/CD-пайплайны невероятно быстрыми, поскольку зависимости кешируются глобально, а не устанавливаются заново для каждого проекта.Вендоринг (Vendoring): Если вам абсолютно необходима полная изоляция (например, для air-gapped сборок), вы можете выполнить
go mod vendor. Это создаст локальную папку vendor, похожую на node_modules, и сборка будет использовать ее.
Команды и инструменты
go mod tidy(npm install):
Эта команда умнее, чем npm install.go mod tidyсканирует ваши .go файлы, смотрит на ваши import statements и делает две вещи: 1) добавляет в go.mod все зависимости, которые вы импортировали, но еще не скачали, и 2) удаляет из go.mod зависимости, которые вы больше не используете. Используйте ее перед каждым коммитом.go get(npm install <pkg>):
Используется для явного добавления новой зависимости или обновления существующей, например,go get github.com/gin-gonic/gin@latest.go run .(ts-node index.ts):
Компилирует и немедленно запускает вашу программу. Идеально для быстрой разработки.go build(tsc / webpack):
Это фундаментальное отличие.npm run buildилиtscтранспайлит TS в JS и бандлит ассеты.go buildкомпилирует ваш код в один статический бинарный файл (например, myapp.exe или myapp). Развертывание вашего приложения это просто копирование этого одного файла на сервер. Вам не нужно запускатьnpm install --productionна сервере.Горячая перезагрузка (Live Reload):
В JS вы привыкли к nodemon или встроенным dev-серверам (HMR). В Go нет встроенной горячей перезагрузки. Сообщество использует сторонние инструменты, самый популярный из которых air. Он работает аналогично nodemon: следит за вашими .go файлами и автоматически перекомпилирует и перезапускает ваш бинарный файл при сохранении.
Структура проекта
Существует неофициальный, но очень популярный репозиторий golang-standards/project-layout. Не используйте его для начала. Он не является официальным стандартом и часто является избыточным для большинства проектов.
Вместо этого придерживайтесь официальных рекомендаций, которые намного проще:
/go.modФайл вашего модуля в корне./cmd/my-app/main.goТочка входа для вашего бинарного файла (приложения). cmd используется, если у вас несколько бинарных файлов (например, сервер и CLI-утилита). Если у вас только один, main.go может лежать в корне./internal/Это самая важная папка. Код в internal не может быть импортирован никаким другим проектом за пределами вашего модуля. Это приватный код вашего приложения, и это правило принудительно enforced компилятором./pkg/Если вы пишете библиотеку, которую должны импортировать другие, поместите этот публичный код сюда.
На этом пока всё, во второй части поговорим об основах языка в сравнении с JS/TS.