Зависит от escape analysis. Компилятор Go решает: если переменная не «убегает» из функции — стек, если убегает (например, возвращается указатель) — куча (heap).
func foo() *int {
x := 42 // аллоцируется на куче — указатель убегает
return &x
}
func bar() int {
x := 42 // аллоцируется на стеке — не убегает
return x
}
Стек горутины начинается с 2-8 КБ и растёт динамически. Проверить escape analysis можно флагом go build -gcflags="-m". Аллокация на стеке бесплатна (просто сдвиг указателя), на куче — требует работы GC.