Что такое синхронное программирование?
Что проверяют
Понимаете ли вы, что «синхронно» это про ожидание результата, а не про количество потоков. В Go вопрос почти всегда ведёт дальше: код на горутинах выглядит последовательным, а под ним работает планировщик, и интервьюер смотрит, знаете ли вы, что именно встаёт в ожидание при вызове.
Как отвечать
Синхронный вызов возвращает управление только после того, как работа закончена: следующая строка не выполнится, пока нет результата или ошибки. Асинхронный возвращает управление сразу, а результат приходит позже через колбэк, future или канал.
Дальше важная для Go часть: язык намеренно оставляет синхронную запись. Здесь нет деления функций на обычные и асинхронные, сетевой вызов пишется как обычная последовательность строк:
resp, err := http.Get(url) // горутина ждёт здесь
if err != nil {
return err
}
defer resp.Body.Close()Ждёт при этом только текущая горутина. Планировщик снимает её с потока операционной системы, отдаёт поток другой горутине, а когда сокет готов, возвращает первую обратно. Параллелизм получают не заменой вызова на асинхронный, а запуском нескольких горутин через go, а согласуют их каналами, sync.WaitGroup или errgroup.
Полезно добавить, что настоящая блокировка потока всё же бывает: вызовы через cgo, часть системных вызовов, длинный счёт. Рантайм заводит дополнительный поток, но цена уже другая.
Где спотыкаются
Считают синхронное однопоточным. Синхронный код прекрасно работает в тысяче горутин сразу, и гонки данных в нём возникают ровно так же: порядок внутри одной горутины ничего не говорит о порядке между разными.
Путают конкурентность и параллелизм. Горутины дают конкурентность всегда, а одновременное исполнение только когда доступно больше одного ядра и GOMAXPROCS это позволяет.
Обещают, что асинхронность ускорит всё подряд. Для задачи, упирающейся в процессор, стиль вызова не меняет ничего: выигрыш появляется там, где программа ждёт сеть или диск.