如果我按值 return 而不是指针,Go 会复制我的结构吗?
Will Go make a copy of my struct if I return by value, instead of a pointer?
举个例子:
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
return 是一个指针,我知道该对象保存在堆中,并且 fff
接收指向同一个堆分配对象的指针。
现在,随着 NewFoo
的第二个实现,它不会 return 一个指针,将 Go return 一个 copy堆栈分配的结构,或者是否有类似 C++'s RVO 的事情发生?
您可以按照以下步骤查看:
把你的程序写在一个文件中说 main.go
像这样:https://play.golang.org/p/iwxai0EHa40
执行命令go build -gcflags=-m main.go
查看输出以真正了解它是否正在 copied/inlined。在我的例子中,我得到的输出是:
# 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 通过各种方式可以使您的程序更有效率。
举个例子:
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
return 是一个指针,我知道该对象保存在堆中,并且 fff
接收指向同一个堆分配对象的指针。
现在,随着 NewFoo
的第二个实现,它不会 return 一个指针,将 Go return 一个 copy堆栈分配的结构,或者是否有类似 C++'s RVO 的事情发生?
您可以按照以下步骤查看:
把你的程序写在一个文件中说
main.go
像这样:https://play.golang.org/p/iwxai0EHa40执行命令
go build -gcflags=-m main.go
查看输出以真正了解它是否正在 copied/inlined。在我的例子中,我得到的输出是:
# 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 通过各种方式可以使您的程序更有效率。