Устройство памяти в golang

Я прочитал, что в язык Голанг менеджит память по-умному. То есть, с помощью escape-анализа го может не аллоцировать память при вызове new и наоборот. Такой вопрос, может ли голанг аллоцировать память при такой записи var bob *Person = &Person{2, 3}. Или всегда указатель будет указывать на стек


Ответы (1 шт):

Автор решения: Pak Uula

Ответ на ваш вопрос: "Всяко бывает".

Вот код с двумя способами использования объектов. В функции 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 размещает объекты.

→ Ссылка