函数内部的变量是在栈上,带指针的变量是在堆上。
func sum(a int, b int) *int {
var c = a + b
return &c
}
c(&c)cc
那么编译器是如何检测的呢,答案是通过逃逸分析。
什么是逃逸分析?逃逸分析:
通过指针的动态范围决定一个变量究竟是分配在栈上还是应该分配在堆上。
我们知道栈区是可以自动清理的,所以栈区的效率很高,但是不可能把所有的对象都申请在栈上面,而且栈空间也是有限的。
但如果所有的对象都分配在堆区的话,堆又不像栈那样可以自动清理,因此会频繁造成垃圾回收,从而降低运行效率。
所以在go中,会通过逃逸分析,把那些一次性的对象分配到栈区,如果后续还有变量指向,那么就放到堆区。
逃逸分析的标准首先可以肯定的是,如果函数里面的变量返回了一个地址,那么这个变量肯定会发生逃逸。
go编译器会判断变量的生命周期,如果编译器认为函数结束后,这个变量不再被外部的引用了,会分配到栈,否则分配到堆。
package main
import "fmt"
func sum(a int, b int) *int {
var c = a + b
var d = 1
var e = new(int)
fmt.Println(&d)
fmt.Println(&e)
return &c
}
d&denew
*因此有两个结论
- 如果一个函数结束之后外部没有引用,那么优先分配到栈中(如果申请的内存过大,栈区存不下,会分配到堆)。
- 如果一个函数结束之后外部还有引用,那么必定分配到堆中。
package main
import "fmt"
func sum(a int, b int) *int {
var c = a + b
return &c
}
func main() {
var p = sum(1, 2)
fmt.Println(*p)
}
go run -gcflags "-m -l" .\main.go
PS E:\TEXT\test_go\test> go run -gcflags "-m -l" .\main.go
# command-line-arguments
.\main.go:6:6: moved to heap: c
.\main.go:12:13: ... argument does not escape
.\main.go:12:14: *p escapes to heap
3
PS E:\TEXT\test_go\test>
c
因为编译期间不确定变量类型的话,那么也会发生逃逸。除此之外,还可以通过反汇编命令来查看:
PS E:\TEXT\test_go\test> go tool compile -S .\main.go
main.sum STEXT size=95 args=0x10 locals=0x18 funcid=0x0 align=0x0
0x0000 00000 (.\main.go:5) TEXT main.sum(SB), ABIInternal, $24-16
0x0000 00000 (.\main.go:5) CMPQ SP, 16(R14)
0x0004 00004 (.\main.go:5) PCDATA $0, $-2
0x0004 00004 (.\main.go:5) JLS 68
0x0006 00006 (.\main.go:5) PCDATA $0, $-1
0x0006 00006 (.\main.go:5) SUBQ $24, SP
0x000a 00010 (.\main.go:5) MOVQ BP, 16(SP)
0x000f 00015 (.\main.go:5) LEAQ 16(SP), BP
0x0014 00020 (.\main.go:5) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0014 00020 (.\main.go:5) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0014 00020 (.\main.go:5) FUNCDATA $5, main.sum.arginfo1(SB)
0x0014 00020 (.\main.go:5) FUNCDATA $6, main.sum.argliveinfo(SB)
0x0014 00020 (.\main.go:5) PCDATA $3, $1
0x0014 00020 (.\main.go:5) MOVQ AX, main.a+32(SP)
0x0019 00025 (.\main.go:5) MOVQ BX, main.b+40(SP)
0x001e 00030 (.\main.go:5) PCDATA $3, $-1
0x001e 00030 (.\main.go:6) LEAQ type.int(SB), AX
0x0025 00037 (.\main.go:6) PCDATA $1, $0
0x0025 00037 (.\main.go:6) CALL runtime.newobject(SB)
0x002a 00042 (.\main.go:6) MOVQ main.b+40(SP), CX
0x002f 00047 (.\main.go:6) MOVQ main.a+32(SP), DX
0x0034 00052 (.\main.go:6) ADDQ DX, CX
0x0037 00055 (.\main.go:6) MOVQ CX, (AX)
0x003a 00058 (.\main.go:7) MOVQ 16(SP), BP
0x003f 00063 (.\main.go:7) ADDQ $24, SP
0x0043 00067 (.\main.go:7) RET
0x0044 00068 (.\main.go:7) NOP
0x0044 00068 (.\main.go:5) PCDATA $1, $-1
0x0044 00068 (.\main.go:5) PCDATA $0, $-2
0x0044 00068 (.\main.go:5) MOVQ AX, 8(SP)
0x0049 00073 (.\main.go:5) MOVQ BX, 16(SP)
0x004e 00078 (.\main.go:5) CALL runtime.morestack_noctxt(SB)
0x0053 00083 (.\main.go:5) MOVQ 8(SP), AX
0x0058 00088 (.\main.go:5) MOVQ 16(SP), BX
0x005d 00093 (.\main.go:5) PCDATA $0, $-1
0x005d 00093 (.\main.go:5) JMP 0
0x0000 49 3b 66 10 76 3e 48 83 ec 18 48 89 6c 24 10 48 I;f.v>H...H.l$.H
0x0010 8d 6c 24 10 48 89 44 24 20 48 89 5c 24 28 48 8d .l$.H.D$ H.\$(H.
0x0020 05 00 00 00 00 e8 00 00 00 00 48 8b 4c 24 28 48 ..........H.L$(H
0x0030 8b 54 24 20 48 01 d1 48 89 08 48 8b 6c 24 10 48 .T$ H..H..H.l$.H
0x0040 83 c4 18 c3 48 89 44 24 08 48 89 5c 24 10 e8 00 ....H.D$.H.\$...
0x0050 00 00 00 48 8b 44 24 08 48 8b 5c 24 10 eb a1 ...H.D$.H.\$...
rel 33+4 t=14 type.int+0
rel 38+4 t=7 runtime.newobject+0
rel 79+4 t=7 runtime.morestack_noctxt+0
main.main STEXT size=111 args=0x0 locals=0x48 funcid=0x0 align=0x0
0x0000 00000 (.\main.go:10) TEXT main.main(SB), ABIInternal, $72-0
0x0000 00000 (.\main.go:10) CMPQ SP, 16(R14)
0x0004 00004 (.\main.go:10) PCDATA $0, $-2
0x0004 00004 (.\main.go:10) JLS 104
0x0006 00006 (.\main.go:10) PCDATA $0, $-1
0x0006 00006 (.\main.go:10) SUBQ $72, SP
0x000a 00010 (.\main.go:10) MOVQ BP, 64(SP)
0x000f 00015 (.\main.go:10) LEAQ 64(SP), BP
0x0014 00020 (.\main.go:10) FUNCDATA $0, gclocals·J5F+7Qw7O7ve2QcWC7DpeQ==(SB)
0x0014 00020 (.\main.go:10) FUNCDATA $1, gclocals·5aa34RaZcmo0NkRpBHp2fg==(SB)
0x0014 00020 (.\main.go:10) FUNCDATA $2, main.main.stkobj(SB)
0x0014 00020 (<unknown line number>) NOP
0x0014 00020 (.\main.go:11) MOVQ $3, main.c+40(SP)
0x001d 00029 (.\main.go:12) MOVUPS X15, main..autotmp_13+48(SP)
0x0023 00035 (.\main.go:12) MOVQ main.c+40(SP), AX
0x0028 00040 (.\main.go:12) PCDATA $1, $1
0x0028 00040 (.\main.go:12) CALL runtime.convT64(SB)
0x002d 00045 (.\main.go:12) LEAQ type.int(SB), CX
0x0034 00052 (.\main.go:12) MOVQ CX, main..autotmp_13+48(SP)
0x0039 00057 (.\main.go:12) MOVQ AX, main..autotmp_13+56(SP)
0x003e 00062 (<unknown line number>) NOP
0x003e 00062 ($GOROOT\src\fmt\print.go:294) MOVQ os.Stdout(SB), BX
0x0045 00069 ($GOROOT\src\fmt\print.go:294) LEAQ go.itab.*os.File,io.Writer(SB), AX
0x004c 00076 ($GOROOT\src\fmt\print.go:294) LEAQ main..autotmp_13+48(SP), CX
0x0051 00081 ($GOROOT\src\fmt\print.go:294) MOVL $1, DI
0x0056 00086 ($GOROOT\src\fmt\print.go:294) MOVQ DI, SI
0x0059 00089 ($GOROOT\src\fmt\print.go:294) PCDATA $1, $0
0x0059 00089 ($GOROOT\src\fmt\print.go:294) CALL fmt.Fprintln(SB)
0x005e 00094 (.\main.go:13) MOVQ 64(SP), BP
0x0063 00099 (.\main.go:13) ADDQ $72, SP
0x0067 00103 (.\main.go:13) RET
0x0068 00104 (.\main.go:13) NOP
0x0068 00104 (.\main.go:10) PCDATA $1, $-1
0x0068 00104 (.\main.go:10) PCDATA $0, $-2
0x0068 00104 (.\main.go:10) CALL runtime.morestack_noctxt(SB)
0x006d 00109 (.\main.go:10) PCDATA $0, $-1
0x006d 00109 (.\main.go:10) JMP 0
0x0000 49 3b 66 10 76 62 48 83 ec 48 48 89 6c 24 40 48 I;f.vbH..HH.l$@H
0x0010 8d 6c 24 40 48 c7 44 24 28 03 00 00 00 44 0f 11 .l$@H.D$(....D..
0x0020 7c 24 30 48 8b 44 24 28 e8 00 00 00 00 48 8d 0d |$0H.D$(.....H..
0x0030 00 00 00 00 48 89 4c 24 30 48 89 44 24 38 48 8b ....H.L$0H.D$8H.
0x0040 1d 00 00 00 00 48 8d 05 00 00 00 00 48 8d 4c 24 .....H......H.L$
0x0050 30 bf 01 00 00 00 48 89 fe e8 00 00 00 00 48 8b 0.....H.......H.
0x0060 6c 24 40 48 83 c4 48 c3 e8 00 00 00 00 eb 91 l$@H..H........
rel 2+0 t=23 type.int+0
rel 2+0 t=23 type.*os.File+0
rel 41+4 t=7 runtime.convT64+0
rel 48+4 t=14 type.int+0
rel 65+4 t=14 os.Stdout+0
rel 72+4 t=14 go.itab.*os.File,io.Writer+0
rel 90+4 t=7 fmt.Fprintln+0
rel 105+4 t=7 runtime.morestack_noctxt+0
go.cuinfo.producer.<unlinkable> SDWARFCUINFO dupok size=0
0x0000 72 65 67 61 62 69 regabi
go.cuinfo.packagename.main SDWARFCUINFO dupok size=0
0x0000 6d 61 69 6e main
go.info.main.sum$abstract SDWARFABSFCN dupok size=37
0x0000 05 6d 61 69 6e 2e 73 75 6d 00 01 01 13 61 00 00 .main.sum....a..
0x0010 00 00 00 00 13 62 00 00 00 00 00 00 0e 63 00 06 .....b.......c..
0x0020 00 00 00 00 00 .....
rel 16+4 t=31 go.info.int+0
rel 24+4 t=31 go.info.int+0
rel 32+4 t=31 go.info.int+0
go.info.fmt.Println$abstract SDWARFABSFCN dupok size=42
0x0000 05 66 6d 74 2e 50 72 69 6e 74 6c 6e 00 01 01 13 .fmt.Println....
0x0010 61 00 00 00 00 00 00 13 6e 00 01 00 00 00 00 13 a.......n.......
0x0020 65 72 72 00 01 00 00 00 00 00 err.......
rel 0+0 t=22 type.[]interface {}+0
rel 0+0 t=22 type.error+0
rel 0+0 t=22 type.int+0
rel 19+4 t=31 go.info.[]interface {}+0
rel 27+4 t=31 go.info.int+0
rel 37+4 t=31 go.info.error+0
main..inittask SNOPTRDATA size=32
0x0000 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................
0x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
rel 24+8 t=1 fmt..inittask+0
go.itab.*os.File,io.Writer SRODATA dupok size=32
0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0010 5a 22 ee 60 00 00 00 00 00 00 00 00 00 00 00 00 Z".`............
rel 0+8 t=1 type.io.Writer+0
rel 8+8 t=1 type.*os.File+0
rel 24+8 t=-32767 os.(*File).Write+0
runtime.nilinterequal·f SRODATA dupok size=8
0x0000 00 00 00 00 00 00 00 00 ........
rel 0+8 t=1 runtime.nilinterequal+0
runtime.memequal64·f SRODATA dupok size=8
0x0000 00 00 00 00 00 00 00 00 ........
rel 0+8 t=1 runtime.memequal64+0
runtime.gcbits.01 SRODATA dupok size=1
0x0000 01 .
type..namedata.*interface {}- SRODATA dupok size=15
0x0000 00 0d 2a 69 6e 74 65 72 66 61 63 65 20 7b 7d ..*interface {}
type.*interface {} SRODATA dupok size=56
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 3b fc f8 8f 08 08 08 36 00 00 00 00 00 00 00 00 ;......6........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.memequal64·f+0
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*interface {}-+0
rel 48+8 t=1 type.interface {}+0
runtime.gcbits.02 SRODATA dupok size=1
0x0000 02 .
type.interface {} SRODATA dupok size=80
0x0000 10 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................
0x0010 39 7a 09 0f 02 08 08 14 00 00 00 00 00 00 00 00 9z..............
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
rel 24+8 t=1 runtime.nilinterequal·f+0
rel 32+8 t=1 runtime.gcbits.02+0
rel 40+4 t=5 type..namedata.*interface {}-+0
rel 44+4 t=-32763 type.*interface {}+0
rel 56+8 t=1 type.interface {}+80
type..namedata.*[]interface {}- SRODATA dupok size=17
0x0000 00 0f 2a 5b 5d 69 6e 74 65 72 66 61 63 65 20 7b ..*[]interface {
0x0010 7d }
type.*[]interface {} SRODATA dupok size=56
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 9d 9c 0e 59 08 08 08 36 00 00 00 00 00 00 00 00 ...Y...6........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.memequal64·f+0
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*[]interface {}-+0
rel 48+8 t=1 type.[]interface {}+0
type.[]interface {} SRODATA dupok size=56
0x0000 18 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 76 de 99 0d 02 08 08 17 00 00 00 00 00 00 00 00 v...............
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*[]interface {}-+0
rel 44+4 t=-32763 type.*[]interface {}+0
rel 48+8 t=1 type.interface {}+0
type..namedata.*[1]interface {}- SRODATA dupok size=18
0x0000 00 10 2a 5b 31 5d 69 6e 74 65 72 66 61 63 65 20 ..*[1]interface
0x0010 7b 7d {}
type.*[1]interface {} SRODATA dupok size=56
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 a8 0e 57 36 08 08 08 36 00 00 00 00 00 00 00 00 ..W6...6........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.memequal64·f+0
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*[1]interface {}-+0
rel 48+8 t=1 type.[1]interface {}+0
type.[1]interface {} SRODATA dupok size=72
0x0000 10 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................
0x0010 6e 20 6a 3d 02 08 08 11 00 00 00 00 00 00 00 00 n j=............
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0040 01 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.nilinterequal·f+0
rel 32+8 t=1 runtime.gcbits.02+0
rel 40+4 t=5 type..namedata.*[1]interface {}-+0
PS E:\TEXT\test_go\test> go tool compile -S .\main.go
main.sum STEXT size=95 args=0x10 locals=0x18 funcid=0x0 align=0x0
0x0000 00000 (.\main.go:5) TEXT main.sum(SB), ABIInternal, $24-16
0x0000 00000 (.\main.go:5) CMPQ SP, 16(R14)
0x0004 00004 (.\main.go:5) PCDATA $0, $-2
0x0004 00004 (.\main.go:5) JLS 68
0x0006 00006 (.\main.go:5) PCDATA $0, $-1
0x0006 00006 (.\main.go:5) SUBQ $24, SP
0x000a 00010 (.\main.go:5) MOVQ BP, 16(SP)
0x000f 00015 (.\main.go:5) LEAQ 16(SP), BP
0x0014 00020 (.\main.go:5) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0014 00020 (.\main.go:5) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0014 00020 (.\main.go:5) FUNCDATA $5, main.sum.arginfo1(SB)
0x0014 00020 (.\main.go:5) FUNCDATA $6, main.sum.argliveinfo(SB)
0x0014 00020 (.\main.go:5) PCDATA $3, $1
0x0014 00020 (.\main.go:5) MOVQ AX, main.a+32(SP)
0x0019 00025 (.\main.go:5) MOVQ BX, main.b+40(SP)
0x001e 00030 (.\main.go:5) PCDATA $3, $-1
0x001e 00030 (.\main.go:6) LEAQ type.int(SB), AX
0x0025 00037 (.\main.go:6) PCDATA $1, $0
0x0025 00037 (.\main.go:6) CALL runtime.newobject(SB)
0x002a 00042 (.\main.go:6) MOVQ main.b+40(SP), CX
0x002f 00047 (.\main.go:6) MOVQ main.a+32(SP), DX
0x0034 00052 (.\main.go:6) ADDQ DX, CX
0x0037 00055 (.\main.go:6) MOVQ CX, (AX)
0x003a 00058 (.\main.go:7) MOVQ 16(SP), BP
0x003f 00063 (.\main.go:7) ADDQ $24, SP
0x0043 00067 (.\main.go:7) RET
0x0044 00068 (.\main.go:7) NOP
0x0044 00068 (.\main.go:5) PCDATA $1, $-1
0x0044 00068 (.\main.go:5) PCDATA $0, $-2
0x0044 00068 (.\main.go:5) MOVQ AX, 8(SP)
0x0049 00073 (.\main.go:5) MOVQ BX, 16(SP)
0x004e 00078 (.\main.go:5) CALL runtime.morestack_noctxt(SB)
0x0053 00083 (.\main.go:5) MOVQ 8(SP), AX
0x0058 00088 (.\main.go:5) MOVQ 16(SP), BX
0x005d 00093 (.\main.go:5) PCDATA $0, $-1
0x005d 00093 (.\main.go:5) JMP 0
0x0000 49 3b 66 10 76 3e 48 83 ec 18 48 89 6c 24 10 48 I;f.v>H...H.l$.H
0x0010 8d 6c 24 10 48 89 44 24 20 48 89 5c 24 28 48 8d .l$.H.D$ H.\$(H.
0x0020 05 00 00 00 00 e8 00 00 00 00 48 8b 4c 24 28 48 ..........H.L$(H
0x0030 8b 54 24 20 48 01 d1 48 89 08 48 8b 6c 24 10 48 .T$ H..H..H.l$.H
0x0040 83 c4 18 c3 48 89 44 24 08 48 89 5c 24 10 e8 00 ....H.D$.H.\$...
0x0050 00 00 00 48 8b 44 24 08 48 8b 5c 24 10 eb a1 ...H.D$.H.\$...
rel 33+4 t=14 type.int+0
rel 38+4 t=7 runtime.newobject+0
rel 79+4 t=7 runtime.morestack_noctxt+0
main.main STEXT size=111 args=0x0 locals=0x48 funcid=0x0 align=0x0
0x0000 00000 (.\main.go:10) TEXT main.main(SB), ABIInternal, $72-0
0x0000 00000 (.\main.go:10) CMPQ SP, 16(R14)
0x0004 00004 (.\main.go:10) PCDATA $0, $-2
0x0004 00004 (.\main.go:10) JLS 104
0x0006 00006 (.\main.go:10) PCDATA $0, $-1
0x0006 00006 (.\main.go:10) SUBQ $72, SP
0x000a 00010 (.\main.go:10) MOVQ BP, 64(SP)
0x000f 00015 (.\main.go:10) LEAQ 64(SP), BP
0x0014 00020 (.\main.go:10) FUNCDATA $0, gclocals·J5F+7Qw7O7ve2QcWC7DpeQ==(SB)
0x0014 00020 (.\main.go:10) FUNCDATA $1, gclocals·5aa34RaZcmo0NkRpBHp2fg==(SB)
0x0014 00020 (.\main.go:10) FUNCDATA $2, main.main.stkobj(SB)
0x0014 00020 (<unknown line number>) NOP
0x0014 00020 (.\main.go:11) MOVQ $3, main.c+40(SP)
0x001d 00029 (.\main.go:12) MOVUPS X15, main..autotmp_13+48(SP)
0x0023 00035 (.\main.go:12) MOVQ main.c+40(SP), AX
0x0028 00040 (.\main.go:12) PCDATA $1, $1
0x0028 00040 (.\main.go:12) CALL runtime.convT64(SB)
0x002d 00045 (.\main.go:12) LEAQ type.int(SB), CX
0x0034 00052 (.\main.go:12) MOVQ CX, main..autotmp_13+48(SP)
0x0039 00057 (.\main.go:12) MOVQ AX, main..autotmp_13+56(SP)
0x003e 00062 (<unknown line number>) NOP
0x003e 00062 ($GOROOT\src\fmt\print.go:294) MOVQ os.Stdout(SB), BX
0x0045 00069 ($GOROOT\src\fmt\print.go:294) LEAQ go.itab.*os.File,io.Writer(SB), AX
0x004c 00076 ($GOROOT\src\fmt\print.go:294) LEAQ main..autotmp_13+48(SP), CX
0x0051 00081 ($GOROOT\src\fmt\print.go:294) MOVL $1, DI
0x0056 00086 ($GOROOT\src\fmt\print.go:294) MOVQ DI, SI
0x0059 00089 ($GOROOT\src\fmt\print.go:294) PCDATA $1, $0
0x0059 00089 ($GOROOT\src\fmt\print.go:294) CALL fmt.Fprintln(SB)
0x005e 00094 (.\main.go:13) MOVQ 64(SP), BP
0x0063 00099 (.\main.go:13) ADDQ $72, SP
0x0067 00103 (.\main.go:13) RET
0x0068 00104 (.\main.go:13) NOP
0x0068 00104 (.\main.go:10) PCDATA $1, $-1
0x0068 00104 (.\main.go:10) PCDATA $0, $-2
0x0068 00104 (.\main.go:10) CALL runtime.morestack_noctxt(SB)
0x006d 00109 (.\main.go:10) PCDATA $0, $-1
0x006d 00109 (.\main.go:10) JMP 0
0x0000 49 3b 66 10 76 62 48 83 ec 48 48 89 6c 24 40 48 I;f.vbH..HH.l$@H
0x0010 8d 6c 24 40 48 c7 44 24 28 03 00 00 00 44 0f 11 .l$@H.D$(....D..
0x0020 7c 24 30 48 8b 44 24 28 e8 00 00 00 00 48 8d 0d |$0H.D$(.....H..
0x0030 00 00 00 00 48 89 4c 24 30 48 89 44 24 38 48 8b ....H.L$0H.D$8H.
0x0040 1d 00 00 00 00 48 8d 05 00 00 00 00 48 8d 4c 24 .....H......H.L$
0x0050 30 bf 01 00 00 00 48 89 fe e8 00 00 00 00 48 8b 0.....H.......H.
0x0060 6c 24 40 48 83 c4 48 c3 e8 00 00 00 00 eb 91 l$@H..H........
rel 2+0 t=23 type.int+0
rel 2+0 t=23 type.*os.File+0
rel 41+4 t=7 runtime.convT64+0
rel 48+4 t=14 type.int+0
rel 65+4 t=14 os.Stdout+0
rel 72+4 t=14 go.itab.*os.File,io.Writer+0
rel 90+4 t=7 fmt.Fprintln+0
rel 105+4 t=7 runtime.morestack_noctxt+0
go.cuinfo.producer.<unlinkable> SDWARFCUINFO dupok size=0
0x0000 72 65 67 61 62 69 regabi
go.cuinfo.packagename.main SDWARFCUINFO dupok size=0
0x0000 6d 61 69 6e main
go.info.main.sum$abstract SDWARFABSFCN dupok size=37
0x0000 05 6d 61 69 6e 2e 73 75 6d 00 01 01 13 61 00 00 .main.sum....a..
0x0010 00 00 00 00 13 62 00 00 00 00 00 00 0e 63 00 06 .....b.......c..
0x0020 00 00 00 00 00 .....
rel 16+4 t=31 go.info.int+0
rel 24+4 t=31 go.info.int+0
rel 32+4 t=31 go.info.int+0
go.info.fmt.Println$abstract SDWARFABSFCN dupok size=42
0x0000 05 66 6d 74 2e 50 72 69 6e 74 6c 6e 00 01 01 13 .fmt.Println....
0x0010 61 00 00 00 00 00 00 13 6e 00 01 00 00 00 00 13 a.......n.......
0x0020 65 72 72 00 01 00 00 00 00 00 err.......
rel 0+0 t=22 type.[]interface {}+0
rel 0+0 t=22 type.error+0
rel 0+0 t=22 type.int+0
rel 19+4 t=31 go.info.[]interface {}+0
rel 27+4 t=31 go.info.int+0
rel 37+4 t=31 go.info.error+0
main..inittask SNOPTRDATA size=32
0x0000 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................
0x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
rel 24+8 t=1 fmt..inittask+0
go.itab.*os.File,io.Writer SRODATA dupok size=32
0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0010 5a 22 ee 60 00 00 00 00 00 00 00 00 00 00 00 00 Z".`............
rel 0+8 t=1 type.io.Writer+0
rel 8+8 t=1 type.*os.File+0
rel 24+8 t=-32767 os.(*File).Write+0
runtime.nilinterequal·f SRODATA dupok size=8
0x0000 00 00 00 00 00 00 00 00 ........
rel 0+8 t=1 runtime.nilinterequal+0
runtime.memequal64·f SRODATA dupok size=8
0x0000 00 00 00 00 00 00 00 00 ........
rel 0+8 t=1 runtime.memequal64+0
runtime.gcbits.01 SRODATA dupok size=1
0x0000 01 .
type..namedata.*interface {}- SRODATA dupok size=15
0x0000 00 0d 2a 69 6e 74 65 72 66 61 63 65 20 7b 7d ..*interface {}
type.*interface {} SRODATA dupok size=56
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 3b fc f8 8f 08 08 08 36 00 00 00 00 00 00 00 00 ;......6........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.memequal64·f+0
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*interface {}-+0
rel 48+8 t=1 type.interface {}+0
runtime.gcbits.02 SRODATA dupok size=1
0x0000 02 .
type.interface {} SRODATA dupok size=80
0x0000 10 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................
0x0010 39 7a 09 0f 02 08 08 14 00 00 00 00 00 00 00 00 9z..............
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
rel 24+8 t=1 runtime.nilinterequal·f+0
rel 32+8 t=1 runtime.gcbits.02+0
rel 40+4 t=5 type..namedata.*interface {}-+0
rel 44+4 t=-32763 type.*interface {}+0
rel 56+8 t=1 type.interface {}+80
type..namedata.*[]interface {}- SRODATA dupok size=17
0x0000 00 0f 2a 5b 5d 69 6e 74 65 72 66 61 63 65 20 7b ..*[]interface {
0x0010 7d }
type.*[]interface {} SRODATA dupok size=56
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 9d 9c 0e 59 08 08 08 36 00 00 00 00 00 00 00 00 ...Y...6........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.memequal64·f+0
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*[]interface {}-+0
rel 48+8 t=1 type.[]interface {}+0
type.[]interface {} SRODATA dupok size=56
0x0000 18 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 76 de 99 0d 02 08 08 17 00 00 00 00 00 00 00 00 v...............
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*[]interface {}-+0
rel 44+4 t=-32763 type.*[]interface {}+0
rel 48+8 t=1 type.interface {}+0
type..namedata.*[1]interface {}- SRODATA dupok size=18
0x0000 00 10 2a 5b 31 5d 69 6e 74 65 72 66 61 63 65 20 ..*[1]interface
0x0010 7b 7d {}
type.*[1]interface {} SRODATA dupok size=56
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 a8 0e 57 36 08 08 08 36 00 00 00 00 00 00 00 00 ..W6...6........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.memequal64·f+0
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*[1]interface {}-+0
rel 48+8 t=1 type.[1]interface {}+0
type.[1]interface {} SRODATA dupok size=72
0x0000 10 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................
0x0010 6e 20 6a 3d 02 08 08 11 00 00 00 00 00 00 00 00 n j=............
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0040 01 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.nilinterequal·f+0
rel 32+8 t=1 runtime.gcbits.02+0
rel 40+4 t=5 type..namedata.*[1]interface {}-+0
rel 44+4 t=-32763 type.*[1]interface {}+0
rel 48+8 t=1 type.interface {}+0
rel 56+8 t=1 type.[]interface {}+0
type..importpath.fmt. SRODATA dupok size=5
0x0000 00 03 66 6d 74 ..fmt
gclocals·g2BeySu+wFnoycgXfElmcg== SRODATA dupok size=8
0x0000 01 00 00 00 00 00 00 00 ........
main.sum.arginfo1 SRODATA static dupok size=5
0x0000 00 08 08 08 ff .....
main.sum.argliveinfo SRODATA static dupok size=2
0x0000 00 00 ..
gclocals·J5F+7Qw7O7ve2QcWC7DpeQ== SRODATA dupok size=8
0x0000 02 00 00 00 00 00 00 00 ........
gclocals·5aa34RaZcmo0NkRpBHp2fg== SRODATA dupok size=10
0x0000 02 00 00 00 02 00 00 00 00 02 ..........
main.main.stkobj SRODATA static size=24
0x0000 01 00 00 00 00 00 00 00 f0 ff ff ff 10 00 00 00 ................
0x0010 10 00 00 00 00 00 00 00 ........
rel 20+4 t=5 runtime.gcbits.02+0
PS E:\TEXT\test_go\test>
总结
堆上动态内存分配的开销比栈要大很多,所以有时我们传递值比传递指针更有效率。
因为复制是栈上完成的操作,开销要比变量逃逸到堆上再分配内存要少的多,比如说:
func func1(a int, b int) *int {
var c = a + b
func2(&c)
}
func func2(p *int){
}
func2func1cfunc2c
因为是栈,所以拷贝值的效率反而会更高一些,要是逃逸到堆、再分配的话,效率反而更低。
因此根据场景具体分析,到底函数要不要接受指针,总之最好学会擅用go语言的逃逸分析。
当然我们不需要知道编译器的逃逸分析规则,只需要观察程序的运行情况就行了。
指针值打印示例在Go语言中,可以使用指针来返回函数的值。
在这个例子中,函数 sum 返回的是一个 int 类型的指针,指向计算结果的内存地址。
因此,我们需要通过指针间接访问计算结果并打印出来。
示例代码如下:
package main
import "fmt"
func sum(a int, b int) *int {
var c = a + b
return &c
}
func main() {
var p = sum(1, 2)
fmt.Println(*p)
}
输出结果为3,即为函数sum的返回值。
需要注意的是,由于返回值指向的是函数内部的局部变量地址,因此在函数返回后,该地址可能已经被重新分配给其他变量,因此不建议在函数外部持有该指针。