Стек горутины стартует с 2 КБ и растет удвоением. Растет он не на месте: рантайм берет новый кусок памяти, копирует туда старый целиком и чинит все указатели, которые смотрели внутрь старого.
Проверяю. Беру адрес локальной переменной, загоняю горутину в рекурсию на 20 тысяч кадров, беру адрес той же переменной снова:
адрес до переезда: 0x107b57a64f50
адрес после: 0x107b57c5ff50
сдвиг: 2076672 байт
значение x: 42
Переменная уехала на 2 МБ и осталась собой. Ни одна строчка моего кода про это не узнала.
Go про все это знает сам, компилятор оставляет карты указателей на каждый кадр. Отсюда и цена горутины в 2 КБ. Можно стартовать с крохотного стека, потому что если не хватит, он переедет.
Код замера лежит в репозитории, каталог stack_move:
go run ./stack_move, адреса на твоей машине будут свои.Механизм целиком, вместе с починкой указателей по картам компилятора, пойдет в серию статей, которую пишу на выходных. Возможно на этой неделе уже выложу 1 часть из 3.
