Устройство памяти в golang
Я прочитал, что в язык Голанг менеджит память по-умному. То есть, с помощью escape-анализа го может не аллоцировать память при вызове new и наоборот. Такой вопрос, может ли голанг аллоцировать память при такой записи var bob *Person = &Person{2, 3}. Или всегда указатель будет указывать на стек
Ответы (1 шт):
Ответ на ваш вопрос: "Всяко бывает".
Вот код с двумя способами использования объектов. В функции main объект локальный, а в f созданный объект возвращается.
package main
type Person struct {
A int
B int
}
func f() *Person {
var bob *Person = &Person{4, 5}
return bob
}
func main() {
var bob *Person = &Person{2, 3}
println(bob)
bob = f()
println(bob)
}
Чтобы посмотреть, что происходит внутри, я предлагаю оттранслировать этот файл в ассемблер: GOOS=linux GOARCH=amd64 go tool compile -S some.go
Аллокация bob внутри f:
0x001d 00029 (some.go:9) LEAQ type."".Person(SB), AX
0x0024 00036 (some.go:9) MOVQ AX, (SP)
0x0028 00040 (some.go:9) PCDATA $1, $0
0x0028 00040 (some.go:9) CALL runtime.newobject(SB)
0x002d 00045 (some.go:9) MOVQ 8(SP), AX
0x0032 00050 (some.go:9) MOVQ $4, (AX)
0x0039 00057 (some.go:9) MOVQ $5, 8(AX)
В стек загружается указатель на дескриптор типа Person и вызывается функция runtime.newobject. Затем по адресу, который возвращает функция, инициализируются поля. То есть объект размещается где-то в памяти, не на стеке.
Аллокация bob внутри main:
0x0021 00033 (some.go:14) XORPS X0, X0
0x0024 00036 (some.go:14) MOVUPS X0, ""..autotmp_4+24(SP)
0x0029 00041 (some.go:14) MOVQ $2, ""..autotmp_4+24(SP)
0x0032 00050 (some.go:14) MOVQ $3, ""..autotmp_4+32(SP)
Как видно, в этом случае bob размещается на стеке.
Это ответ на ваш вопрос, правда? Временный объект создаётся на стеке, а нелокальный размещается в памяти.
Но на самом деле всё ещё занятнее.
Функцию f компилятор оптимизирует нафиг. Вместо вызова f компилятор создаёт структуру Person{4,5} таки на стеке.
0x005e 00094 (some.go:9) XORPS X0, X0
0x0061 00097 (some.go:9) MOVUPS X0, ""..autotmp_6+8(SP)
0x0066 00102 (some.go:9) MOVQ $4, ""..autotmp_6+8(SP)
0x006f 00111 (some.go:9) MOVQ $5, ""..autotmp_6+16(SP)
Поэтому я на вашем месте не пытался бы предсказывать, где именно Go размещает объекты.