No está muy claro para mí en cuyo caso querría usar un receptor de valor en lugar de usar siempre un receptor de puntero.
Para recapitular de los 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
Los documentos también dicen: "Para tipos como tipos básicos, porciones y estructuras pequeñas, un receptor de valores es muy barato, por lo que, a menos que la semántica del método requiera un puntero, un receptor de valores es eficiente y claro".
El primer punto dice que es "muy barato", pero la pregunta es más si es más barato que el receptor de puntero. Así que hice un pequeño punto de referencia (código en esencia) que me mostró que el receptor de puntero es más rápido incluso para una estructura que tiene solo un campo de cadena. Estos son los 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: tenga en cuenta que el segundo punto dejó de ser válido en las versiones más recientes de Go, consulte los comentarios) .
Segundo punto dice, es "eficiente y claro" lo que es más una cuestión de gustos, ¿no? Personalmente, prefiero la coherencia al usarlo en todas partes de la misma manera. ¿Eficiencia en qué sentido? En cuanto al rendimiento, parece que los punteros son casi siempre más eficientes. Pocas pruebas con una propiedad int mostraron una ventaja mínima del receptor Value (rango de 0.01-0.1 ns / op)
¿Alguien puede decirme un caso en el que un receptor de valores claramente tenga más sentido que un receptor de puntero? ¿O estoy haciendo algo mal en el punto de referencia? ¿Pasé por alto otros factores?