Горутина стартует с небольшим стеком (порядка 2 КБ в современных версиях Go). При необходимости стек автоматически растёт.
Потоки ОС обычно имеют фиксированный стек 1-8 МБ. Поэтому можно запускать тысячи горутин, но не тысячи потоков.
// Тысячи горутин - нормально
for i := 0; i < 100000; i++ {
go func() { /* малый стек на старте */ }()
}
Рост стека прозрачен для кода и не требует изменений в программе.