Backend-разработчик на Go: Путь от новичка до Big Tech

Интенсивный курс, сочетающий теорию с созданием практических мини-проектов для портфолио. Вы освоите синтаксис Go, конкурентность, базы данных и архитектуру микросервисов, необходимых для трудоустройства в Яндекс, Ozon или финтех.

1. Основы Go: Настройка окружения, синтаксис и первый консольный проект

Основы Go: Настройка окружения, синтаксис и первый консольный проект

Добро пожаловать в курс «Backend-разработчик на Go». Вы сделали отличный выбор. Go (или Golang) — это язык, на котором держится современная облачная инфраструктура. Docker, Kubernetes, Prometheus — все эти гиганты написаны на Go. В России этот язык является стандартом де-факто для высоконагруженных систем в таких компаниях, как Яндекс, Ozon, Wildberries, Avito и Тинькофф.

В этой первой статье мы пройдем путь от «чистого листа» до вашего первого работающего приложения. Мы не будем тратить время на скучную теорию без практики. Наша цель — сразу начать писать код, который работает.

Почему Go идеален для старта?

Go был создан в Google в 2009 году с конкретной целью: повысить продуктивность разработчиков и решить проблемы масштабируемости. Он сочетает в себе производительность C++ и читаемость Python.

Ключевые преимущества:

* Простота. В спецификации языка всего около 25 ключевых слов. * Строгая статическая типизация. Компилятор найдет большинство ваших ошибок еще до запуска программы. * Скорость. Go компилируется в машинный код, что делает его невероятно быстрым. * Встроенная конкурентность. Работа с тысячами параллельных процессов — это «фишка» Go, о которой мы поговорим в следующих модулях.

!Процесс превращения исходного кода Go в исполняемый бинарный файл

Шаг 1: Настройка окружения

Чтобы стать профессионалом, нужно использовать профессиональные инструменты. Нам понадобятся две вещи: компилятор Go и среда разработки (IDE).

Установка Go

  • Перейдите на официальный сайт The Go Programming Language.
  • Скачайте установщик для вашей операционной системы (Windows, macOS или Linux).
  • Запустите установщик и следуйте инструкциям.
  • После установки откройте терминал (PowerShell в Windows или Terminal в macOS/Linux) и введите команду:

    Если вы увидите что-то вроде go version go1.21.0 ..., значит, вы готовы к работе.

    Выбор IDE

    Для комфортной разработки я рекомендую один из двух вариантов:

    * VS Code (бесплатно). Самый популярный редактор. Обязательно установите официальное расширение «Go» от команды Go Team. * GoLand (платно, есть пробный период). Мощная IDE от JetBrains, стандарт в крупных компаниях.

    Для начала курса VS Code будет более чем достаточно.

    Шаг 2: Структура программы и Hello World

    В Go весь код организован в пакеты. Это фундаментальное понятие. Любая запускаемая программа должна начинаться с пакета main.

    Создайте папку для вашего проекта, например go-course, и внутри создайте файл main.go. Напишем наш первый код:

    Разберем каждую строку:

  • package main: Сообщает компилятору, что этот файл является точкой входа в программу и должен быть скомпилирован в исполняемый файл.
  • import "fmt": Подключает пакет fmt (format), который содержит функции для форматирования ввода и вывода (аналог printf в C или print в Python).
  • func main() { ... }: Главная функция. Именно отсюда начинается выполнение программы.
  • Запуск программы

    В терминале, находясь в папке с файлом, выполните:

    Команда go run компилирует и сразу запускает программу без создания бинарного файла на диске. Это удобно для разработки.

    Если вы хотите создать настоящий .exe (или бинарник для Linux/Mac), используйте:

    Шаг 3: Переменные и типы данных

    Go — язык со статической типизацией. Это значит, что тип переменной определяется при компиляции и не может меняться в процессе работы. Это спасает от множества багов, с которыми сталкиваются разработчики на Python или JavaScript.

    Объявление переменных

    Существует два основных способа создания переменных:

    1. Полная форма (через var): Используется, когда мы хотим явно указать тип или объявить переменную без начального значения (она получит «нулевое значение»).

    2. Краткая форма (через :=): Самый популярный способ. Компилятор сам догадается о типе данных. Работает только внутри функций.

    > Важно: В Go нельзя объявить переменную и не использовать её. Компилятор выдаст ошибку. Это приучает писать чистый код без мусора.

    Основные типы данных

    | Тип | Описание | Пример | | :--- | :--- | :--- | | int | Целое число (зависит от архитектуры, обычно 64 бита) | 42, -10 | | float64 | Число с плавающей точкой (двойная точность) | 3.14, 0.001 | | string | Строка (набор символов UTF-8) | "Привет" | | bool | Логический тип | true, false |

    Шаг 4: Управляющие конструкции

    Синтаксис Go минималистичен. Здесь нет while или do-while. Есть только for и if.

    Условный оператор if

    Скобки вокруг условия не нужны, а фигурные скобки {} обязательны.

    Цикл for

    Единственный цикл в Go. Он может работать как классический for, как while и как бесконечный цикл.

    Практика: Консольный проект «Финансовый помощник»

    Теория без практики мертва. Давайте напишем мини-приложение, которое поможет вам отслеживать финансы. Это будет консольная утилита, где можно вносить доходы и расходы.

    Задача

    Реализовать программу, которая:

  • Показывает текущий баланс.
  • Позволяет добавить транзакцию (положительное число — доход, отрицательное — расход).
  • Работает в цикле, пока пользователь не выберет выход.
  • Реализация

    Создайте новый файл wallet.go.

    1. Инициализация модуля В современных проектах Go принято использовать Go Modules. В терминале выполните:

    Это создаст файл go.mod, который описывает ваш проект.

    2. Написание кода

    Разбор ключевых моментов проекта

  • fmt.Scan(&choice): Мы используем &, чтобы передать адрес переменной. Функция Scan должна изменить значение переменной choice, поэтому ей нужен доступ к месту в памяти, где эта переменная лежит. О указателях мы поговорим позже, пока просто запомните этот синтаксис для ввода.
  • balance += amount: Краткая запись для balance = balance + amount.
  • break: Ключевое слово для немедленного выхода из цикла.
  • %.2f: Форматирование вывода числа с плавающей точкой — оставляет только два знака после запятой.
  • Заключение

    Поздравляю! Вы только что написали свое первое интерактивное приложение на Go. Вы настроили окружение, освоили базовый синтаксис, переменные, циклы и ввод/вывод.

    В следующей статье мы углубимся в структуры данных: массивы, слайсы и карты (maps), чтобы наш «Финансовый помощник» мог запоминать историю операций, а не только итоговую сумму.

    Ваш путь в Big Tech начался. Не останавливайтесь!

    2. Глубокое погружение: Структуры, интерфейсы и идиоматичная обработка ошибок

    Глубокое погружение: Структуры, интерфейсы и идиоматичная обработка ошибок

    Приветствую, будущий архитектор высоконагруженных систем! Мы продолжаем наш путь к вершинам Backend-разработки. В прошлых статьях мы разобрали фундамент: переменные, циклы, массивы и слайсы. Но чтобы строить небоскребы (вроде микросервисов Ozon или Avito), кирпичей и цемента недостаточно. Нам нужны чертежи и стандарты.

    Сегодня мы переходим к «большой тройке» концепций Go, которые отличают код новичка от кода инженера Big Tech:

  • Структуры — как моделировать реальные объекты.
  • Интерфейсы — как делать код гибким и заменяемым.
  • Обработка ошибок — почему в Go нет исключений (try-catch) и почему это гениально.
  • Часть 1: Структуры (Structs) — замена классам

    Если вы пришли из Java, C# или Python, забудьте слово «класс». В Go нет классов, нет наследования в привычном понимании и нет перегрузки методов. Go пропагандирует композицию вместо наследования.

    Структура — это типизированная коллекция полей. Это ваш собственный тип данных, который объединяет несколько переменных под одним именем.

    Объявление и создание

    Представим, мы разрабатываем сервис доставки. Нам нужно описать курьера.

    Теперь мы можем создать конкретного курьера:

    !Чертеж структуры как описание типа данных и готовый объект как экземпляр этой структуры

    Методы: Оживляем структуры

    Структура — это просто данные. Чтобы добавить поведение, мы создаем методы. Метод — это функция, у которой есть специальный аргумент — получатель (receiver).

    Value Receiver vs Pointer Receiver

    Это критически важный момент, на котором «сыпятся» новички на собеседованиях.

  • Value Receiver (c Courier): Метод получает копию структуры. Если вы измените поля внутри метода, оригинал не изменится.
  • Pointer Receiver (c *Courier): Метод получает ссылку на структуру. Изменения затронут оригинал.
  • > Золотое правило: Если метод должен изменять состояние структуры или структура большая (чтобы не копировать много данных в памяти) — используйте указатель *.

    Встраивание (Embedding) вместо наследования

    Go использует композицию. Вы можете встроить одну структуру в другую.

    Часть 2: Интерфейсы — контракт превыше всего

    Интерфейсы в Go — это, пожалуй, самая мощная фича языка. Они позволяют писать код, который зависит от поведения, а не от конкретной реализации.

    Интерфейс — это набор сигнатур методов. Если тип реализует все эти методы, он автоматически удовлетворяет интерфейсу. Не нужно писать implements, как в Java или PHP. Это называется Duck Typing («Утиная типизация»): «Если это выглядит как утка, плавает как утка и крякает как утка, то это, вероятно, и есть утка».

    Пример: Платежная система

    Представьте, что вы пишете процессинг для интернет-магазина. Вы хотите принимать оплату картами, ApplePay и бонусами.

    Теперь создадим типы, которые реализуют этот метод:

    Магия происходит здесь. Мы можем написать функцию, которая принимает любой тип, удовлетворяющий интерфейсу Payer.

    !Розетка символизирует интерфейс, а разные вилки — различные структуры, реализующие этот интерфейс

    Пустой интерфейс interface{} (или any)

    Интерфейс без методов называется пустым. Ему удовлетворяет абсолютно любой тип данных (int, string, struct). Это аналог Object в Java.

    С версии Go 1.18 вместо interface{} можно использовать алиас any.

    Часть 3: Обработка ошибок — Errors are Values

    В Go нет try, catch, throw или finally. Ошибки — это обычные значения, которые возвращаются из функции последним аргументом.

    Это сделано намеренно. Код с исключениями часто скрывает логику потока управления (GOTO-подобное поведение). В Go поток управления всегда явен.

    Стандартный паттерн

    Конструкция if err != nil станет вашим самым часто набираемым кодом. И это хорошо. Это заставляет вас думать о том, что может пойти не так, в каждой точке программы.

    Тип error

    На самом деле error — это просто встроенный интерфейс:

    Вы можете создавать свои типы ошибок, просто реализовав метод Error().

    Практика: Система уведомлений для банка

    Давайте объединим структуры, интерфейсы и ошибки в мини-проекте. Мы напишем систему рассылки уведомлений клиентам банка.

    Задача

  • Есть клиенты с Email и телефоном.
  • Нужно уметь отправлять уведомления по Email и SMS.
  • Если телефон не указан, отправка SMS должна возвращать ошибку.
  • Реализация

    Разбор полетов

  • Мы создали интерфейс Sender. Функции NotifyClient абсолютно всё равно, как именно будет доставлено сообщение — по почте, смс или голубиной почтой. Главное, чтобы у объекта был метод Send.
  • Мы обработали ошибки. В случае с sms без номера телефона программа не упала, а корректно сообщила об ошибке.
  • Заключение

    Сегодня вы сделали огромный шаг вперед. Структуры и интерфейсы — это скелет любого Go-приложения. Именно на них строятся чистая архитектура и микросервисы.

    В следующей статье мы разберем тему, ради которой многие и выбирают Go — Горутины и Каналы. Мы научимся выполнять тысячи задач одновременно.

    Готовьтесь, будет быстро и мощно!

    3. Магия Go: Конкурентность, горутины и каналы для высоконагруженных систем

    Магия Go: Конкурентность, горутины и каналы для высоконагруженных систем

    Приветствую, коллега! Мы подошли к экватору нашего курса, и сегодня перед вами откроется главная причина, почему Go стал языком №1 для облачных технологий и микросервисов. Если структуры и интерфейсы — это скелет приложения, то конкурентность — это его нервная система, позволяющая делать тысячи дел одновременно.

    В этой статье мы разберем, как писать код, который использует 100% ресурсов процессора, не взрывая при этом мозг сложностью, как это бывает в C++ или Java.

    Конкурентность vs Параллелизм

    Прежде чем писать код, нужно разобраться в терминах. Их часто путают.

    Конкурентность (Concurrency) — это способность программы иметь дело* с множеством задач одновременно. Это про структуру программы. Представьте одного бармена, который принимает заказ, пока кофемашина варит кофе для предыдущего клиента. Он переключается между задачами. Параллелизм (Parallelism) — это выполнение* множества задач одновременно. Это про железо. Представьте двух барменов, работающих за двумя кофемашинами одновременно.

    Go позволяет писать конкурентный код, который автоматически становится параллельным, если у вашего процессора есть несколько ядер.

    Горутины (Goroutines)

    В большинстве языков для параллельной работы используются потоки операционной системы (OS Threads). Они тяжелые. Создание одного потока занимает около 1 МБ оперативной памяти.

    В Go придумали горутины. Это «легковесные потоки», которыми управляет не операционная система, а сам Go Runtime (планировщик Go).

    Давайте посчитаем разницу в потреблении памяти, используя простую математику:

    Где — общий объем памяти, — количество потоков, а — размер стека одного потока.

    Для Java (OS Thread) при и :

    Для Go (Goroutine) при и :

    Разница колоссальная! Вы можете запустить миллион горутин на обычном ноутбуке, и он не зависнет. Именно поэтому Go идеален для HighLoad.

    !Визуальное сравнение потребления памяти потоками ОС и горутинами

    Запуск горутины

    Чтобы запустить функцию в отдельной горутине, нужно просто добавить ключевое слово go перед вызовом.

    Если вы запустите этот код, то, скорее всего, увидите только Привет из main!. Почему? Потому что функция main — это тоже горутина. Когда она завершается, программа закрывается, убивая все остальные горутины, даже если они не успели выполниться.

    Синхронизация с WaitGroup

    Чтобы дождаться выполнения горутин, мы используем примитив синхронизации WaitGroup из пакета sync.

    > Важно: Всегда передавайте WaitGroup в функции по указателю. Если передать по значению, скопируется внутренний счетчик, и main никогда не узнает о завершении работы.

    Каналы (Channels): Общение без боли

    Горутины работают отлично, но как им обмениваться данными? В других языках используют общую память и мьютексы (блокировки), что часто приводит к сложным багам (Race Conditions).

    Философия Go гласит: > Не общайтесь, используя общую память. Используйте общую память, общаясь.

    Для этого существуют каналы. Канал — это типизированная труба, через которую одна горутина отправляет данные, а другая принимает.

    !Иллюстрация работы каналов как средства передачи данных между горутинами

    Создание и использование

    Блокировки и Deadlock

    По умолчанию каналы небуферизированные. Это значит, что:

  • Отправка chan <- val блокирует горутину, пока кто-то не прочитает из канала.
  • Чтение <- chan блокирует горутину, пока кто-то не напишет в канал.
  • Если вы попытаетесь читать и писать в одной горутине без пары, вы получите Deadlock (взаимную блокировку).

    Буферизированные каналы

    Можно создать канал с емкостью. Он не блокирует отправку, пока в нем есть место.

    Закрытие канала и range

    Мы можем читать из канала в цикле for range, пока он не будет закрыт отправителем.

    Конструкция Select

    Что делать, если нам нужно ждать ответа от нескольких каналов одновременно? Например, мы ждем данные из базы и тайм-аут. Для этого есть select — аналог switch, но для каналов.

    В примере выше сработает ветка тайм-аута, так как данные придут только через 2 секунды, а таймер сработает через 1 секунду. Это критически важный паттерн для микросервисов, чтобы не зависать при ожидании ответа от сторонних систем.

    Практика: Быстрый чекер сайтов

    Давайте напишем утилиту, которая проверяет доступность списка сайтов. Сначала мы могли бы сделать это последовательно, но это долго. Сделаем это конкурентно!

    Задача

    Проверить статус код (200 OK) для списка URL. Использовать горутины для ускорения.

    Реализация

    Разбор магии

  • Мы запускаем 5 горутин практически одновременно.
  • Программа не ждет, пока ответит Google, чтобы начать проверять Yandex.
  • Время выполнения всей программы будет равно времени ответа самого медленного сайта, а не сумме всех времен.
  • Если бы мы делали это без горутин, проверка 5 сайтов по 1 секунде заняла бы 5 секунд. С горутинами — около 1 секунды.

    Заключение

    Вы только что прикоснулись к самой мощной части Go. Горутины и каналы позволяют строить системы, обрабатывающие миллионы запросов (как в Wildberries в «Черную пятницу»), используя ресурсы эффективно.

    В следующей статье мы применим эти знания для создания вашего первого настоящего HTTP веб-сервера. Мы научимся принимать запросы из браузера и отдавать JSON-ответы.

    Ваш путь в Big Tech становится всё интереснее. Не переключайтесь!

    4. Backend в действии: Протокол HTTP, создание REST API и работа с базами данных SQL

    Backend в действии: Протокол HTTP, создание REST API и работа с базами данных SQL

    Приветствую, коллега! Мы прошли долгий путь: настроили окружение, изучили синтаксис, освоили структуры и интерфейсы, и даже научились управлять тысячами горутин. Теперь у вас есть все инструменты, чтобы построить настоящий Backend.

    В этой статье мы перейдем от консольных утилит к тому, чем занимаются разработчики в Яндекс, Ozon или Тинькофф каждый день. Мы создадим веб-сервер, который принимает запросы из интернета, обрабатывает данные и сохраняет их в базу данных.

    Сегодня мы разберем:

  • Протокол HTTP: Как клиенты и серверы понимают друг друга.
  • REST API: Стандарт общения современных сервисов.
  • JSON: Как превратить структуры Go в понятный браузеру формат.
  • SQL и database/sql: Как надежно хранить данные.
  • Часть 1: Протокол HTTP — язык интернета

    Когда вы открываете сайт ozon.ru, ваш браузер (клиент) отправляет сообщение на сервер Ozon. Сервер обрабатывает его и отправляет ответ. Этот обмен сообщениями происходит по протоколу HTTP (HyperText Transfer Protocol).

    !Визуализация цикла запрос-ответ между клиентом и сервером

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

    Каждый HTTP-запрос состоит из метода (действия) и пути (ресурса). В REST-архитектуре принято использовать методы следующим образом:

    * GET — получить данные (например, список товаров). * POST — создать новые данные (оформить заказ). * PUT/PATCH — обновить данные (изменить адрес доставки). * DELETE — удалить данные.

    Сервер отвечает статус-кодом. Вы наверняка видели 404 Not Found. Вот основные группы кодов:

    * 2xx (Success): Все прошло успешно (например, 200 OK). * 4xx (Client Error): Ошибка клиента (например, 400 Bad Request — неверные данные). * 5xx (Server Error): Ошибка сервера (например, 500 Internal Server Error — сервер упал).

    Часть 2: Ваш первый веб-сервер на Go

    В отличие от Python (где нужен Django/FastAPI) или Java (Spring), в Go есть мощнейшая стандартная библиотека net/http. Она настолько хороша, что многие высоконагруженные сервисы используют именно её, не прибегая к сторонним фреймворкам.

    Создадим файл server.go:

    Запустите этот код (go run server.go) и откройте в браузере http://localhost:8080/backend. Вы увидите: Привет! Вы обратились к /backend.

    Часть 3: JSON и REST API

    Современные бэкенды редко отдают просто текст или HTML. Они отдают данные в формате JSON, чтобы их могли прочитать мобильные приложения или фронтенд (React/Vue).

    В Go работа с JSON реализована через пакет encoding/json. Чтобы научить наши структуры превращаться в JSON, мы используем теги.

    Теги структур

    Создаем API для магазина

    Давайте напишем ручку (handler), которая отдает товар в формате JSON.

    Теперь при запросе сервер вернет:

    Часть 4: Работа с базой данных SQL

    Хранить данные в переменных памяти (как мы делали раньше) — плохая идея. Если сервер перезагрузится, все данные пропадут. Нам нужна база данных (БД).

    В Go есть универсальный интерфейс database/sql. Он позволяет работать с любой SQL-базой (PostgreSQL, MySQL, SQLite), меняя только драйвер.

    В Big Tech стандартом де-факто является PostgreSQL. Но для обучения мы рассмотрим общие принципы, которые работают везде.

    Подключение к БД

    Для работы нам понадобится драйвер. Обычно его устанавливают через go get. Представим, что мы используем PostgreSQL.

    Выполнение запросов

    В database/sql есть два основных метода:

  • Exec — для запросов, которые не возвращают строки (INSERT, UPDATE, DELETE).
  • Query / QueryRow — для выборки данных (SELECT).
  • !Go приложение отправляет SQL запросы в базу данных через драйвер

    Пример: Добавление товара (INSERT)

    Обратите внимание на 2. Это плейсхолдеры. Никогда не подставляйте переменные в строку запроса через fmt.Sprintf! Это приведет к уязвимости SQL Injection, и хакеры украдут всю вашу базу.

    Пример: Получение товара (SELECT)

    Практика: Собираем все вместе

    Давайте объединим HTTP, JSON и SQL в мини-сервис. Представим, что у нас уже есть подключение к БД в переменной db.

    Задача: Реализовать обработчик создания товара через POST-запрос.

    Почему это важно для Big Tech?

    В крупных компаниях (Яндекс, Авито) бэкенд состоит из сотен таких микросервисов. Каждый из них делает что-то одно: один хранит пользователей, другой — товары, третий — корзину. Все они общаются по HTTP (или gRPC, о котором позже) и сохраняют данные в базы.

    Понимая, как работает net/http и database/sql, вы понимаете фундамент, на котором строятся системы, обслуживающие миллионы пользователей.

    Заключение

    Сегодня вы сделали огромный рывок. Вы научились: * Принимать HTTP-запросы. * Работать с JSON. * Безопасно выполнять SQL-запросы.

    В следующей статье мы поговорим об Архитектуре приложения. Вы узнаете, как не превратить код в «спагетти», как правильно раскладывать файлы по папкам и что такое «Чистая архитектура» (Clean Architecture), которую требуют на собеседованиях.

    Код пишется, сервер работает. До встречи в следующем модуле!

    5. Продакшн: Тестирование, Docker, архитектура микросервисов и подготовка к собеседованию

    Продакшн: Тестирование, Docker, архитектура микросервисов и подготовка к собеседованию

    Поздравляю! Вы прошли огромный путь. Вы знаете синтаксис Go, умеете работать с конкурентностью, базами данных и HTTP. Ваш код работает на вашем ноутбуке. Но в мире Big Tech (Яндекс, Ozon, Google) фраза «у меня локально всё работает» не принимается.

    Код должен быть надежным, легко разворачиваемым и поддерживаемым. В этой финальной статье мы превратим ваш любительский проект в профессиональный продукт. Мы поговорим о том, как пишут код сеньоры, как упаковать приложение в контейнер и как пройти собеседование, чтобы получить оффер мечты.

    Часть 1: Тестирование — страховка от багов

    В динамических языках (Python, JS) тесты нужны, чтобы проверить типы. В Go компилятор проверяет типы за вас, но он не может проверить бизнес-логику.

    В Go тестирование — это не сторонний фреймворк, а часть стандартной библиотеки testing. Файлы с тестами должны называться _test.go и лежать рядом с проверяемым кодом.

    Простой Unit-тест

    Допустим, у нас есть функция сложения в файле math.go:

    Создадим файл math_test.go:

    Запуск тестов выполняется командой:

    Table-Driven Tests (Табличные тесты)

    Это «золотой стандарт» в Go. Вместо того чтобы копировать if result != expected десять раз, мы создаем таблицу (слайс структур) с входными данными и ожиданиями.

    Такой подход позволяет легко добавлять новые кейсы, просто добавляя строку в слайс tests.

    Часть 2: Docker — «Работает везде»

    Чтобы ваше приложение запускалось одинаково и на MacBook разработчика, и на сервере Linux в дата-центре, мы используем Docker. Это технология контейнеризации.

    Go идеально подходит для Docker. Программы на Go компилируются в один бинарный файл, которому (обычно) не нужны внешние зависимости.

    !Сравнение архитектуры Виртуальных Машин и Контейнеров

    Пишем Dockerfile

    Создайте файл с именем Dockerfile (без расширения) в корне проекта.

    Плохой пример (но рабочий):

    Этот образ будет весить около 800 МБ, потому что он содержит весь компилятор Go и исходники.

    Профессиональный пример (Multi-stage build): Мы используем один образ для сборки, а другой (крошечный) — для запуска.

    Результат: образ весом 10-20 МБ. Это критически важно для быстрой выкладки (деплоя) в облако.

    Часть 3: Архитектура и структура проекта

    Когда вы пишете main.go на 1000 строк — это Монолит (и плохой код). В Go сообществе принят стандарт Standard Go Project Layout.

    Структура папок

    * cmd/ — Точка входа. Здесь лежит main.go. Логики здесь быть не должно, только запуск. * cmd/myapp/main.go * internal/ — Приватный код библиотеки. Этот код не могут импортировать другие проекты. Здесь живет вся бизнес-логика. * pkg/ — Публичный код, который можно использовать в других проектах (например, утилиты для валидации). * api/ — Описание API (Swagger/OpenAPI файлы).

    Чистая архитектура (Clean Architecture)

    Чтобы код не превратился в спагетти, его делят на слои:

  • Handler (Transport Layer): Отвечает за HTTP (парсит JSON, валидирует запросы). Вызывает Service.
  • Service (Business Logic): Самая важная часть. Здесь живут правила (например, «нельзя перевести денег больше, чем есть на счете»). Вызывает Repository.
  • Repository (Data Layer): Работает с базой данных (SQL запросы). Ничего не знает про HTTP.
  • !Слои Чистой Архитектуры: Зависимости направлены только внутрь

    Часть 4: Микросервисы vs Монолит

    В начале пути (стартап) лучше писать Монолит — одно приложение, которое делает всё. Его проще деплоить и отлаживать.

    Когда компания растет (как Ozon или Avito), монолит распиливают на Микросервисы. * Сервис авторизации. * Сервис корзины. * Сервис каталога.

    Они общаются друг с другом по сети (REST API или gRPC). Go — король микросервисов благодаря своей легкости и производительности.

    Часть 5: Подготовка к собеседованию

    Вы готовы искать работу. Что вас спросят?

    1. Алгоритмическая сложность (Big O)

    Вас обязательно спросят про эффективность кода. Вы должны понимать, почему поиск в массиве медленнее поиска в карте (map).

    Сложность алгоритма часто описывается формулой:

    где — время выполнения алгоритма, — размер входных данных, а — верхняя граница роста времени выполнения (функция сложности).

    Примеры: * (Константное время): Взять значение из Map по ключу. Время не зависит от размера карты. * (Линейное время): Пройтись циклом for по слайсу. Если элементов стало в 2 раза больше, время выросло в 2 раза.

    2. Внутренности Go (Hard Skills)

    * Слайсы: Как работают len и cap? Что происходит при append, если cap переполнен? (Ответ: создается новый массив в 2 раза больше, данные копируются). * Map: Почему порядок перебора map случайный? (Ответ: защита от хакеров и особенности реализации). * Concurrency: Чем буферизированный канал отличается от небуферизированного? Что такое Race Condition?

    3. System Design

    На позицию Middle могут попросить спроектировать систему, например, «Аналог Twitter». * Какую базу данных выберете? (PostgreSQL для пользователей, Cassandra/ClickHouse для лайков). * Как будете масштабировать? (Балансировщики нагрузки, кэширование в Redis).

    4. Soft Skills

    Не будьте токсичным. Умейте объяснять свои решения. Если не знаете ответа — скажите честно «Я не знаю, но я бы искал ответ так...».

    Заключение курса

    Мы прошли путь от `fmt.Println(