举这个例子:
type Foo struct {
num int
}
// func NewFoo() *Foo { // returning a pointer
// return &Foo{33}
// }
func NewFoo() Foo { // NOT returning a pointer
return Foo{33}
}
func main() {
fff := NewFoo()
fmt.Printf("%d\n", fff.num)
}
如果NewFoo
返回一个指针,我理解该对象保留在堆中,并且fff
接收到指向同一堆已分配对象的指针。
现在,使用NewFoo
的第二种实现,该实现不会返回指针,会Go返回堆栈分配结构的copy,还是会发生类似C++'s RVO的事情?
您可以按照以下步骤进行检查:
在文件中将程序写成main.go
,如下所示:https://play.golang.org/p/iwxai0EHa40
执行命令go build -gcflags=-m main.go
查看输出以真正知道它是否正在被复制/内联。就我而言,我得到的输出是:
# command-line-arguments
./main.go:13:6: can inline NewFoo
./main.go:17:6: can inline main
./main.go:18:15: inlining call to NewFoo
./main.go:19:12: inlining call to fmt.Printf
./main.go:19:24: fff.num escapes to heap
./main.go:19:12: io.Writer(os.Stdout) escapes to heap
./main.go:19:12: main []interface {} literal does not escape
<autogenerated>:1: os.(*File).close .this does not escape
您可以在任何Go程序中遵循此过程,以检查程序中是否有不必要的堆分配,可以避免。
Here is a short article通过各种方式使您的程序更有效。