在 Go 中有多种方法可以返回一个struct值或它的切片。对于我见过的个人:
struct
type MyStruct struct { Val int } func myfunc() MyStruct { return MyStruct{Val: 1} } func myfunc() *MyStruct { return &MyStruct{} } func myfunc(s *MyStruct) { s.Val = 1 }
我了解这些之间的差异。第一个返回结构的副本,第二个是指向在函数内创建的结构值的指针,第三个期望传入一个现有的结构并覆盖该值。
我已经看到所有这些模式在各种上下文中使用,我想知道关于这些的最佳实践是什么。你什么时候用哪个?例如,第一个可能适用于小型结构(因为开销很小),第二个适用于较大的结构。第三个如果你想获得极高的内存效率,因为你可以轻松地在调用之间重用单个结构实例。是否有关于何时使用哪个的最佳实践?
同样,关于切片的相同问题:
func myfunc() []MyStruct { return []MyStruct{ MyStruct{Val: 1} } } func myfunc() []*MyStruct { return []MyStruct{ &MyStruct{Val: 1} } } func myfunc(s *[]MyStruct) { *s = []MyStruct{ MyStruct{Val: 1} } } func myfunc(s *[]*MyStruct) { *s = []MyStruct{ &MyStruct{Val: 1} } }
再说一遍:这里的最佳实践是什么。我知道切片总是指针,所以返回一个指向切片的指针是没有用的。但是,我是否应该返回一个结构值切片,一个指向结构的指针,我是否应该将指向切片的指针作为参数传递
您应该经常使用指针的一种情况:
比其他参数更频繁地是指针。方法修改它们被调用的东西,或者命名类型是大结构,所以
指导是
默认为指针,除非在极少数情况下。
一些不需要指针的情况:
type Point struct { latitude, longitude float64 }
bytes.Replace
int
io.Reader.Read(p []byte)
p
append
interface{}
flag.StringVar
*string
使用指针的地方:
x
reader.WriteTo(writer)
bytes.Buffer
Reset()
existingUser.LoadFromJSON(json []byte) error
NewUserFromJSON(json []byte) (*User, error)
sync.Pool
最后,关于您的切片是否应该是指针:值的切片可能很有用,并节省您的分配和缓存未命中。可能有拦截器:
NewFoo() *Foo
sync.Mutex
从广义上讲,如果您将所有项目放在前面并且不移动它们(例如,append在初始设置后不再移动s),或者如果您确实继续移动它们但您确定这是好的(不/小心使用指向项目的指针,项目足够小以有效复制等)。有时您必须考虑或衡量您的情况的具体情况,但这是一个粗略的指南。