我是Go的新手,在编写struct" functions"时,我真的无法决定何时使用指针与副本。 (这是正确的术语吗?)
type Blah struct {
c complex128
s string
f float64
}
func (b * Blah) doPtr() {
fmt.Println(b.c, b.s, b.f);
}
func (b Blah) doCopy() {
fmt.Println(b.c, b.s, b.f);
}
现在,我的C ++背景告诉我doPtr
在速度和内存方面都更有效率,但是很多示例都使用doCopy
,除非您正在修改对象,所以我错过了一些东西?
答案 0 :(得分:8)
[Go] Frequently Asked Questions (FAQ)
Should I define methods on values or pointers?
对于基本类型,切片和小结构等类型,值 接收器非常便宜,所以除非方法的语义要求 一个指针,一个值接收器是高效和清晰的。
对于性能问题,不要猜。运行基准。例如,
档案:bench_test.go
package main
import (
"testing"
)
type Blah struct {
c complex128
s string
f float64
}
func (b *Blah) doPtr() {
}
func (b Blah) doCopy() {
}
func BenchmarkDoPtr(b *testing.B) {
blah := Blah{}
for i := 0; i < b.N; i++ {
(&blah).doPtr()
}
}
func BenchmarkDoCopy(b *testing.B) {
blah := Blah{}
for i := 0; i < b.N; i++ {
blah.doCopy()
}
}
输出:
$ go test -bench=.
testing: warning: no tests to run
PASS
BenchmarkDoPtr 2000000000 1.26 ns/op
BenchmarkDoCopy 50000000 32.6 ns/op
ok so/test 4.317s
$
答案 1 :(得分:2)
来自Go Programming Language Phrasebook, Chapter4 - by David Chisnall(IMO,一本优秀的书。)
...另一个原因是它意味着这个方法不需要指向结构。这非常重要,因为它与Go类型系统有什么关系。 如果通过接口调用方法,则接受指针的方法只有在接口变量包含指针时才可调用。
例如,您可以定义一个定义Log()方法的接口并创建此类型的变量。然后,您可以将Logger结构的实例分配给该变量。您还可以将指向Logger结构实例的指针指定给此变量。两者都可以工作,因为Log()方法可以从结构的实例和指向实例的指针调用。如果该方法采用指针参数,那么您只能在指针上调用它。 因此Go中的好样式只需要在修改结构时需要方法来获取指针,或者如果结构太大以至于在每次方法调用时复制它都会让人望而却步......