Mengapakah menggunakan `t` lwn `*t` sebagai penerima dalam `fmt.Stringer` Go membawa kepada gelung mati?

Patricia Arquette
Lepaskan: 2024-11-22 22:49:12
asal
686 orang telah melayarinya

Why does using `t` vs `*t` as a receiver in Go's `fmt.Stringer` lead to a dead loop?

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())
}
Salin selepas log masuk

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)
}
Salin selepas log masuk

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))
}
Salin selepas log masuk

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!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan