Não está claro para mim em que caso eu gostaria de usar um receptor de valor em vez de sempre usar um receptor de ponteiro.
Para recapitular os documentos:
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
A documentação também diz "Para tipos como tipos básicos, fatias e pequenas estruturas, um receptor de valor é muito barato, portanto, a menos que a semântica do método exija um ponteiro, um receptor de valor é eficiente e claro."
Primeiro ponto ele diz que é "muito barato", mas a questão é mais se é mais barato do que o receptor de ponteiro. Então fiz um pequeno benchmark (code on gist) que me mostrou que o receptor de ponteiro é mais rápido mesmo para uma estrutura que tem apenas um campo de string. Estes são os resultados:
// 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
(Editar: observe que o segundo ponto se tornou inválido nas versões mais recentes de go, consulte os comentários) .
Segundo ponto , é "eficiente e claro", o que é mais uma questão de gosto, não é? Pessoalmente, prefiro consistência usando todos os lugares da mesma maneira. Eficiência em que sentido? Em termos de desempenho, parece que os ponteiros são quase sempre mais eficientes. Poucos testes com uma propriedade int mostraram vantagem mínima do receptor Value (intervalo de 0,01-0,1 ns / op)
Alguém pode me dizer um caso em que um receptor de valor claramente faz mais sentido do que um receptor de ponteiro? Ou estou fazendo algo errado no benchmark, esqueci outros fatores?