> Что такое синхронное программирование? (Go)

Уровень: junior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Моторика

Стек: Go

> Пример ответа

Короткий ответ

Синхронное программирование - это модель выполнения, при которой код исполняется последовательно, строка за строкой. Каждая операция блокирует поток до своего завершения, и следующая инструкция не начнётся, пока текущая не закончится. В Go это базовое поведение внутри одной goroutine: вызов функции, чтение из сети или запись в файл приостанавливают выполнение до получения результата.

Подробное объяснение

В синхронной модели управление передаётся линейно: программа выполняет инструкции в том порядке, в котором они написаны. Если операция долгая - например, сетевой запрос или чтение с диска - поток ожидает её завершения и не делает ничего полезного в это время. Это упрощает рассуждение о коде: нет гонок за порядком выполнения, состояние меняется предсказуемо, а ошибки обрабатываются сразу после вызова. В Go синхронность - это норма внутри одной goroutine, но сам runtime устроен так, что блокирующие системные вызовы не обязательно блокируют весь процесс: планировщик может переключиться на другие goroutine. Важно различать синхронный код и синхронный ввод-вывод: первый описывает порядок инструкций, второй - способ ожидания результата.

На практике

В backend на Go синхронный стиль используется постоянно: обработчик HTTP-запроса читает тело, идёт в базу, формирует ответ - всё последовательно. Это читаемо и легко отлаживается. Проблемы начинаются, когда таких запросов много: если каждый блокирует поток на время ожидания БД, страдает пропускная способность. Поэтому на практике синхронный код комбинируют с конкурентностью: несколько goroutine выполняют синхронные операции параллельно, а каналы или sync.WaitGroup синхронизируют результат. Такой подход даёт простоту линейного кода и масштаб конкурентной обработки.

Пример кода

GO
package main
import (
"fmt"
"net/http"
"io"
)
func fetch(url string) (string, error) {
resp, err := http.Get(url) // блокирует до ответа
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) // тоже блокирует
if err != nil {
return "", err
}
return string(body), nil
}
func main() {
// последовательно: второй запрос начнётся только после первого
body, err := fetch("https://example.com")
if err != nil {
fmt.Println("ошибка:", err)
return
}
fmt.Println("длина ответа:", len(body))
}

Как отвечать на собеседовании

Скажите, что синхронное программирование - это последовательное выполнение, где каждая операция блокирует поток до завершения. Подчеркните, что в Go это базовый режим внутри goroutine, а конкурентность достигается запуском нескольких goroutine, каждая из которых может писать синхронный код. Упомяните trade-off: простота и предсказуемость против потенциального простоя при ожидании ввода-вывода. Покажите, что понимаете разницу между синхронным кодом и блокирующими вызовами.

Что проверяет интервьюер

Понимание базовой модели выполнения и того, как она соотносится с конкурентностью в Go. Умение объяснить, почему синхронный код проще отлаживать, и где он становится узким местом. Способность не путать синхронность с последовательностью в одном потоке и блокирующий ввод-вывод. Проверяется также, видит ли кандидат практические последствия: пропускную способность, задержки, необходимость goroutine.

Типичные ошибки

Говорить, что синхронный код всегда медленный - это не так, он может быть быстрее конкурентного за счёт отсутствия накладных расходов на синхронизацию. Путать синхронность с однопоточностью: синхронный код может выполняться в нескольких потоках или goroutine. Считать, что блокирующий вызов в Go блокирует весь процесс, хотя планировщик может переключиться на другую goroutine. Забывать про обработку ошибок сразу после вызова, что в синхронной модели является естественным и обязательным.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью