Memahami Perbezaan Antara t dan *t: Kajian Kes daripada Pakej fmt
Dalam Go, pakej fmt menyediakan keupayaan pemformatan yang hebat , membenarkan pembangun menyesuaikan cara nilai dicetak. Walau bagaimanapun, perbezaan halus antara t dan *t boleh membawa kepada tingkah laku yang tidak dijangka, iaitu gelung mati apabila digunakan dalam kaedah penerima.
Pertimbangkan coretan kod berikut:
package main import "fmt" type TT struct { a int b float32 c string } func (t *TT) String() string { return fmt.Sprintf("%+v", *t) } func main() { tt := &TT{3, 4, "5"} fmt.Printf(tt.String()) }
Kod ini akan dilaksanakan dengan jayanya, mencetak kandungan pembolehubah 'tt' sebagai "tt={a:3, b:4, c:5}". Walau bagaimanapun, jika kita mengubah suai kaedah String seperti berikut:
func (t *TT) String() string { return fmt.Sprintf("%+v", t) }
Ia akan mengakibatkan gelung mati. Sebabnya terletak pada cara pakej fmt mengendalikan nilai yang melaksanakan kaedah String() (melaksanakan antara muka fmt.Stringer).
Apabila nilai 'tt' dihantar ke fmt.Println, pakej fmt menyemak sama ada jenis TT melaksanakan kaedah String(). Memandangkan kami mentakrifkan kaedah String() dengan penerima penuding (*TT), kaedah yang ditetapkan untuk TT tidak termasuk String(). Akibatnya, pakej fmt tidak memanggil tt.String().
Sebaliknya, dalam coretan kod yang diubah suai, kami mentakrifkan kaedah String() dengan jenis penerima *TT. Dalam kes ini, kaedah yang ditetapkan untuk TT termasuk String(). Walau bagaimanapun, memandangkan kami menghantar tt yang jenis *TT, memanggil tt.String() pada asasnya memanggil kaedah String() secara rekursif, menghasilkan gelung tak terhingga.
Untuk mengelakkan isu ini, adalah dinasihatkan untuk gunakan jenis penerima yang berbeza untuk kaedah String(). Satu pendekatan ialah mencipta jenis baharu menggunakan kata kunci jenis dan melakukan penukaran jenis pada nilai yang diluluskan. Ini mencipta jenis baharu tanpa kaedah, mengelakkan gelung tak terhingga.
Contohnya:
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
Dalam kes ini, menukar t kepada TT2 dengan berkesan memastikan kaedah String() tidak akan dipanggil secara rekursif, kerana TT2 tidak mempunyai kaedah String().
Memahami perbezaan antara t dan *t dalam konteks pakej fmt adalah penting untuk mengelakkan tingkah laku yang tidak dijangka dan memastikan pelaksanaan kod yang cekap.
Atas ialah kandungan terperinci Mengapakah menggunakan `t` lwn `*t` sebagai penerima dalam `fmt.Stringer` Go membawa kepada gelung mati?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!