Горутина - это легковесный поток выполнения, управляемый рантаймом Go (не поток ОС). Начальный размер стека около 2 КБ; поток ОС обычно 1-8 МБ. Поэтому можно запускать десятки и сотни тысяч горутин.
Планировщик Go мультиплексирует горутины на небольшое число потоков ОС (GOMAXPROCS). При блокировке (канал, системный вызов) горутина может быть отложена, а поток переключится на другую горутину.
for i := 0; i < 10000; i++ {
go func(n int) { doWork(n) }(i)
}
Запуск горутины дешёвый; они не привязаны 1:1 к потокам ОС.