如果我有这样的结构
type myStruct struct {
mystring string
myint int
}
如果我有一个返回像这样的新myStruct的函数
func New() myStruct {
s := myStruct{}
s.mystring = "string"
s.myint = 1
return s
}
因为我在返回它之前首先将它存储在“s”变量中,我的函数实际上是在制作2个myStruct值而不是一个吗?
如果是这样,那么确保我不首先将其存储在变量中是一种更好的做法吗?
答案 0 :(得分:11)
return
语句将返回myStruct
对象值的副本。如果它是一个小物体,那么这很好。
如果您希望调用者能够修改此对象,并且该struct将具有使用指针作为接收器的方法,那么返回指向结构的指针更有意义:
func New() *myStruct {
s := myStruct{}
s.mystring = "string"
s.myint = 1
return &s
}
比较值的内存地址与指针返回类型时,您可以看到发生的副本:http://play.golang.org/p/sj6mivYSHg
package main
import (
"fmt"
)
type myStruct struct {
mystring string
myint int
}
func NewObj() myStruct {
s := myStruct{}
fmt.Printf("%p\n", &s)
return s
}
func NewPtr() *myStruct {
s := &myStruct{}
fmt.Printf("%p\n",s)
return s
}
func main() {
o := NewObj()
fmt.Printf("%p\n",&o)
p := NewPtr()
fmt.Printf("%p\n",p)
}
0xf8400235a0 // obj inside NewObj()
0xf840023580 // obj returned to caller
0xf840023640 // ptr inside of NewPtr()
0xf840023640 // ptr returned to caller
答案 1 :(得分:3)
我绝对不是Go专家(甚至是新手:)),但正如@ max.haredoom所提到的,你可以在函数签名本身中分配变量。这样,您也可以省略s
中的return
:
package main
import "fmt"
type myStruct struct {
mystring string
myint int
}
func New() (s myStruct) {
s.mystring = "string"
s.myint = 1
return
}
func main() {
r := New()
fmt.Println(r)
}
// Outputs {string 1}
在我Effective Go中遇到的例子中,它似乎是处理这种性质的最常见方式,但同样,我绝对不是这个主题的权威(并且会看起来有关实际表现的其他信息)。
答案 2 :(得分:0)
我想我通过使用延迟找到了答案。
我更新了函数,以便对myStruct值进行延迟修改。这意味着它将在返回之后发生,但在另一端收到它之前。
当我这样做时,调用者接收的结构不会显示更新的值,所以看起来好像我确实要返回一个副本。
func New() myStruct {
s := myStruct{}
defer func() {
s.mystring = "new value" // defer an update to the value
}()
s.mystring = "string"
s.myint = 1
return s
}
func main() {
b := New()
fmt.Println(b) // still shows the original value
}