Golang语言中如何确定是否发生逃逸

1.使用go提供的指令

package main

import "fmt"

func func() *int {
    a := 3
    return &a

}

func main() {
    b := func()
    fmt.Println(*b)
}

执行编译指令:go build -gcflags ‘-m -l’ main.go

  • -gcflags 用于请用编译器支持的额外标志;
  • -m 用于输出编译器优化细节(包括使用逃逸分析这种优化);
  • -N 用来关闭编译器优化;
  • -l 用于禁用函数的内联优化,防止逃逸编译器通过内联彻底的抹除;
    输出结果:
# command-line-arguments
./main.go:6: moved to heap: a
./main.go:7: &a escapes to heap
./main.go:13: *b escapes to heap
./main.go:13: main ... argument does not escape

我们来分析一下结果,很明显,变量a发生了逃逸,被分配到堆内存。但是有一点大家可能不明白main函数中的b也发生了逃逸,这是因为fmt.Println(a …interface{})参数是interface,编译期间很难确定其具体类型,这种情况也会发生逃逸。

2.使用反汇编命令

go tool compile -S main.go
终端输出结果:

"".foo t=1 size=64 value=0 args=0x8 locals=0x10
        0x0000 00000 (main.go:5)        TEXT    "".foo(SB), $16-8
        0x0000 00000 (main.go:5)        MOVQ    (TLS), CX
        0x0009 00009 (main.go:5)        CMPQ    SP, 16(CX)
        0x000d 00013 (main.go:5)        JLS     57
        0x000f 00015 (main.go:5)        SUBQ    $16, SP
        0x0013 00019 (main.go:5)        FUNCDATA        $0, gclocals·5184031d3a32a42d85027f073f873668(SB)
        0x0013 00019 (main.go:5)        FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0013 00019 (main.go:6)        LEAQ    type.int(SB), BX
        0x001a 00026 (main.go:6)        MOVQ    BX, (SP)
        0x001e 00030 (main.go:6)        PCDATA  $0, $0
        0x001e 00030 (main.go:6)        CALL    runtime.newobject(SB)
        0x0023 00035 (main.go:6)        MOVQ    8(SP), AX
        0x0028 00040 (main.go:6)        MOVQ    $3, (AX)
        0x002f 00047 (main.go:7)        MOVQ    AX, "".~r0+24(FP)
        0x0034 00052 (main.go:7)        ADDQ    $16, SP
        0x0038 00056 (main.go:7)        RET
        0x0039 00057 (main.go:7)        NOP
        0x0039 00057 (main.go:5)        CALL    runtime.morestack_noctxt(SB)
        0x003e 00062 (main.go:5)        JMP     0
        0x0000 64 48 8b 0c 25 00 00 00 00 48 3b 61 10 76 2a 48  dH..%....H;a.v*H
        0x0010 83 ec 10 48 8d 1d 00 00 00 00 48 89 1c 24 e8 00  ...H......H..$..
        0x0020 00 00 00 48 8b 44 24 08 48 c7 00 03 00 00 00 48  ...H.D$.H......H
        0x0030 89 44 24 18 48 83 c4 10 c3 e8 00 00 00 00 eb c0  .D$.H...........
        // 因为输出的比较多,我们值取重要的部分,其他部分省略

结果分析,0x001e 00030 (main.go:6) CALL runtime.newobject(SB) 用于分配内存到堆上,说明a被存放到堆上了,也就是发生了逃逸。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值