Это очень неясно для меня, и в этом случае я хотел бы использовать приемник значений вместо того, чтобы всегда использовать приемник указателя.
Резюмируя из документации:Приемник-приемник по отношению к приемнику указателя в Голанге?
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
The документов говорит также «Для таких типов, как основные типов, ломтики и малые структуры, значение приемника очень дешево, поэтому, если семантика методы требует указатель, приемник значений эффективен и понятен ».
Первый пункт говорит, что это «очень дешево», но вопрос в том, что он дешевле, чем приемник указателя. Поэтому я сделал небольшой тест (code on gist), который показал мне, что приемник указателя быстрее даже для структуры, которая имеет только одно поле строки. Таковы результаты:
// Struct one empty string property
BenchmarkChangePointerReceiver 2000000000 0.36 ns/op
BenchmarkChangeItValueReceiver 500000000 3.62 ns/op
// Struct one zero int property
BenchmarkChangePointerReceiver 2000000000 0.36 ns/op
BenchmarkChangeItValueReceiver 2000000000 0.36 ns/op
(Edit: Обратите внимание, что второй пункт стал недействительным в новых версиях отыщите комментариев).
Второй пункт Он говорит, что это «эффективный и понятный», который больше зависит от вкуса, не так ли? Лично я предпочитаю согласованность, используя везде одинаково. Эффективность в каком смысле? Похоже, что указатель почти всегда более эффективен. Несколько тестовых прогонов с одним свойством int показали минимальное преимущество приемника значений (диапазон 0,01-0,1 нс/оп)
Может ли кто-нибудь сказать мне случай, когда приемник значений явно имеет больше смысла, чем приемник указателя? Или я делаю что-то неправильно в бенчмарке, не упустил ли я другие факторы?
Я побежал аналогичные тесты с одного поля строки, а также с двумя полями: строка и INT поля. Я получаю более быстрые результаты от приемника значений. BenchmarkChangePointerReceiver-4 \t \t 10000000000 0,99 нс/оп BenchmarkChangeItValueReceiver-4 0,33 нс/оп Это использование Go 1.8. Интересно, были ли оптимизаторы компилятора сделаны с момента последнего запуска тестов. Дополнительную информацию см. В [gist] (https://gist.github.com/pbitty/aaf143ce98907eb1687bc0eff28a436b). – pbitty
Вы правы. Запуск моего исходного теста с использованием Go1.9, теперь я получаю разные результаты. Pointer Receiver 0.60 ns/op, приемник значений 0.38 ns/op – Chrisport