2 回答
TA贡献1784条经验 获得超9个赞
(不完全是一个答案,但对于评论来说太大了。)
从评论看来你可能对这个小例子感兴趣:
package main
type Foo struct {
i, j, k int
}
func NewFoo() *Foo {
return &Foo{i: 42}
}
func F1() {
f := NewFoo()
f.i++
}
func main() {
F1()
}
在 Go1.5 上运行go build -gcflags="-m"给出:
./new.go:7: can inline NewFoo
./new.go:11: can inline F1
./new.go:12: inlining call to NewFoo
./new.go:16: can inline main
./new.go:17: inlining call to F1
./new.go:17: inlining call to NewFoo
./new.go:8: &Foo literal escapes to heap
./new.go:12: F1 &Foo literal does not escape
./new.go:17: main &Foo literal does not escape
因此,内联NewFoo成F1成main(并说,它可能会进一步直列main如果有人是称呼它)。虽然它确实说NewFoo本身会&Foo逃逸,但内联时并不会逃逸。
输出通过初始化堆栈上的对象而不执行任何函数调用来go build -gcflags="-m -S"确认这一点main。
当然,这是一个非常简单的例子,任何复杂的情况(例如调用fmt.Printwith f)都可能很容易导致它逃逸。一般来说,除非分析告诉您存在问题区域并且您正在尝试优化特定的代码部分,否则您不必担心太多。惯用和可读的代码应该胜过优化。
另请注意,使用go test -bench -benchmem(或最好使用testing.B'sReportAllocs方法)可以报告基准代码的分配,这可以帮助识别比预期/期望的分配更多的事情。
- 2 回答
- 0 关注
- 174 浏览
添加回答
举报