Ответ
Горутины в Go эффективны для любых задач, которые можно выполнять конкурентно или асинхронно. Их использование наиболее оправдано в следующих сценариях:
Высококонкурентные I/O-операции (I/O-bound задачи). Это основной сценарий. Когда горутина ожидает ответа от сети, базы данных или чтения файла, планировщик Go не блокирует поток ОС, а переключает его на выполнение других горутин.
- Обработка HTTP-запросов в веб-серверах.
- Взаимодействие с базами данных и кэшами.
- Работа с файловой системой.
Параллельные вычисления (CPU-bound задачи). Для задач, требующих интенсивных вычислений (математические расчеты, обработка изображений), горутины позволяют распараллелить нагрузку на несколько ядер процессора (
GOMAXPROCS
).Фоновые задачи. Выполнение периодических или долгоживущих задач, которые не должны блокировать основной поток приложения: сбор метрик, логирование, очистка кэша.
Пример: конкурентная обработка URL
func fetchURL(url string, wg *sync.WaitGroup) {
defer wg.Done()
// Имитация работы
resp, err := http.Get(url)
if err != nil {
fmt.Printf("%s: %sn", url, err)
return
}
defer resp.Body.Close()
fmt.Printf("%s: %sn", url, resp.Status)
}
func main() {
var wg sync.WaitGroup
urls := []string{"https://go.dev", "https://golang.org", "https://invalid.url"}
for _, url := range urls {
wg.Add(1)
go fetchURL(url, &wg)
}
// Ожидаем завершения всех горутин
wg.Wait()
}
Ключевое преимущество горутин — их легковесность. Они занимают всего ~2KB памяти (в отличие от мегабайтов для потоков ОС), а их переключение происходит очень быстро внутри рантайма Go, а не на уровне ядра ОС.