Sangat tidak jelas bagi saya dalam hal ini saya ingin menggunakan penerima nilai daripada selalu menggunakan penerima penunjuk.
Ringkasan dari dokumen:
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 docs mengatakan juga "Untuk jenis seperti tipe dasar, iris, dan struct kecil, penerima nilai sangat murah jadi kecuali semantik metode membutuhkan pointer, penerima nilai efisien dan jelas."
Poin pertama dikatakan "sangat murah", tetapi pertanyaannya adalah apakah lebih murah dari pada penerima pointer. Jadi saya membuat patokan kecil (kode pada intinya) yang menunjukkan kepada saya, penerima penunjuk itu lebih cepat bahkan untuk struct yang hanya memiliki satu bidang string. Inilah hasilnya:
// 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: Harap dicatat bahwa poin kedua menjadi tidak valid di versi go yang lebih baru, lihat komentar) .
Poin kedua mengatakan, "efisien dan jelas" yang lebih merupakan masalah selera, bukan? Secara pribadi saya lebih suka konsistensi dengan menggunakan cara yang sama di mana-mana. Efisiensi dalam arti apa? kinerja bijaksana tampaknya penunjuk hampir selalu lebih efisien. Beberapa uji coba dengan satu properti int menunjukkan keuntungan minimal penerima Nilai (kisaran 0,01-0,1 ns / op)
Dapatkah seseorang memberi tahu saya kasus di mana penerima nilai jelas lebih masuk akal daripada penerima penunjuk? Atau apakah saya melakukan sesuatu yang salah dalam benchmark, apakah saya mengabaikan faktor-faktor lain?
Jawaban:
Perhatikan bahwa FAQ memang menyebutkan konsistensi
Seperti yang disebutkan di utas ini :
Sekarang:
The Kode Ulasan komentar dapat membantu:
Bagian yang dicetak tebal ditemukan misalnya dalam
net/http/server.go#Write()
:sumber
The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers
Sebenarnya tidak benar. Metode penerima nilai dan penerima pointer dapat dipanggil pada pointer atau non-pointer yang diketik dengan benar. Terlepas dari apa metode dipanggil, di dalam tubuh metode, pengenal penerima merujuk ke nilai by-copy ketika penerima nilai digunakan, dan penunjuk ketika penerima pointer digunakan: Lihat play.golang.org/p / 3WHGaAbURMInt(5).increment_by_one_ptr()
. Demikian pula, sifat yang mendefinisikan metodeincrement_by_one_ptr
tidak akan puas dengan nilai tipeInt
.Untuk menambahkan tambahan ke @VonC jawaban yang bagus dan informatif.
Saya terkejut tidak ada yang benar-benar menyebutkan biaya pemeliharaan setelah proyek menjadi lebih besar, pengembang lama pergi dan yang baru datang. Go pasti adalah bahasa yang masih muda.
Secara umum, saya mencoba menghindari petunjuk ketika saya bisa tetapi mereka memiliki tempat dan keindahannya sendiri.
Saya menggunakan pointer ketika:
Misalnya:
Alasan mengapa saya menghindari petunjuk:
Aturan praktis saya, tulis sebanyak mungkin metode yang dienkapsulasi seperti:
MEMPERBARUI:
Pertanyaan ini menginspirasi saya untuk meneliti topik lebih lanjut dan menulis posting blog tentangnya https://medium.com/gophersland/gopher-vs-object-oriented-golang-4fa62b88c701
sumber