从内存分配策略(堆、栈)的角度分析,函数传递指针真的比传值效率高吗?git
持续更新于个人 Github ,欢迎 Stargithub
介绍golang
对于初学者,确定不少同窗在纠结:shell
分析bash
要找到区别,那确定须要下功夫,那就从 Golang 的实现机制中来分析吧。首先,在Golang 中有一个很重要的概念那就是 逃逸分析(Escape analysis),所谓的逃逸分析指由编译器决定内存分配的位置。闭包
最终程序的执行效率和这个两种分配规则是有这重要关联的,而传值和传指针的主要区别在于底层值是否须要拷贝,表面上看传指针不涉及值拷贝,效率确定更高。可是实际状况是指传针会涉及到变量逃逸到堆上,并且会增长GC的负担,因此本文咱们要作的内容就是进行 逃逸分析 ,按照惯例先上结论。函数
每种方式都有各自的优缺点,栈上的值,减小了 GC 的压力,可是要维护多个副本,堆上的指针,会增长 GC 的压力,但只需维护一个值。所以选择哪一种方式,依据本身的业务状况参考这个标准进行选择。性能
先上一段代码分析下ui
// escape.go
package main
type person struct {
name string
age int
}
func main() {
makePerson(32, "艾玛·斯通")
showPerson(33, "杨幂")
}
func makePerson(age int, name string) *person {
maliya := person{name, age}
return &maliya
}
func showPerson(age int, name string) person {
yangmi := person{name, age}
return yangmi
}
复制代码
运行以下命令,进行逃逸分析spa
go build -gcflags="-m -m -l" escape.go
复制代码
输出结果:
Escape/Escape.go:15:9: &maliya escapes to heap
Escape/Escape.go:15:9: from ~r2 (return) at Escape/Escape.go:15:2
Escape/Escape.go:14:2: moved to heap: maliya
Escape/Escape.go:13:40: leaking param: name to result ~r2 level=-1
Escape/Escape.go:13:40: from person literal (struct literal element) at Escape/Escape.go:14:18
Escape/Escape.go:13:40: from maliya (assigned) at Escape/Escape.go:14:9
Escape/Escape.go:13:40: from &maliya (address-of) at Escape/Escape.go:15:9
Escape/Escape.go:13:40: from ~r2 (return) at Escape/Escape.go:15:2
Escape/Escape.go:18:39: leaking param: name to result ~r2 level=0
Escape/Escape.go:18:39: from person literal (struct literal element) at Escape/Escape.go:19:18
Escape/Escape.go:18:39: from yangmi (assigned) at Escape/Escape.go:19:9
Escape/Escape.go:18:39: from ~r2 (return) at Escape/Escape.go:20:2
复制代码
从结果中咱们看到变量 &maliya 发生了逃逸,变量 yangmi 没有逃逸
&maliya escapes to heap from ~r2 (return) at Escape/Escape.go:15:2
moved to heap: maliya
复制代码
因此 makePerson 返回的是指针类型,发生了逃逸,而showPerson 返回的是值类型没有逃逸。
关于变量逃逸的状况还有不少,网上有不少分析的文章,就不一一举例了,直接给出结论: