Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapakah Go mengembalikan penunjuk kepada pembalut ralat tetapi mengisytiharkannya dengan "ralat" dan bukannya "* ralat"

Mengapakah Go mengembalikan penunjuk kepada pembalut ralat tetapi mengisytiharkannya dengan "ralat" dan bukannya "* ralat"

WBOY
WBOYke hadapan
2024-02-09 22:40:10549semak imbas

为什么 Go 返回一个指向错误包装器的指针,但用“error”而不是“*error”声明它

Mengapa Go mengembalikan penunjuk kepada pembalut ralat tetapi mengisytiharkannya dengan "ralat" dan bukannya "ralat"? Ini adalah masalah biasa yang dihadapi oleh ramai pembangun bahasa Go. Ringkasnya, cara Go mengembalikan ralat adalah untuk memudahkan penggunaan dan pengendalian ralat. Dalam Go, ralat ialah jenis antara muka yang mempunyai kaedah Ralat() yang mengembalikan mesej ralat. Oleh itu, apabila fungsi mengembalikan ralat, ia sebenarnya mengembalikan penunjuk kepada struktur yang melaksanakan kaedah Ralat(). Reka bentuk ini menjadikan pengendalian ralat lebih ringkas dan fleksibel, mengurangkan lebihan kod dan kerumitan. Oleh itu, semasa mengembalikan penunjuk mungkin kelihatan pelik, ia sebenarnya bertujuan untuk memberikan pengendalian ralat yang lebih baik.

Kandungan soalan

Saya sedang belajar bahasa Go dari latar belakang Java.

type MyError struct {
    message string
    Offset  int
}

func (Me *MyError) Error() string {
    return Me.message
}

func myFunction() (int, error) {      <-- Why the return type is "error" rather than "*error"
    return 0, &MyError{"my error message", 0} <-- The error is returned as a pointer.
}

func main() {
    var _, err = myFunction()
    if e, ok := err.(*MyError); ok {.  <-- Why I can assert err which is a type of "error" into a pointer
        fmt.Printf("Error is %s: %d\n", e.message, e.Offset)
    }
}

Dalam kod di atas, saya tidak faham mengapa jenis ralat myFunction ialah "error" dan bukannya "*error"? Saya dengan jelas mengembalikan penunjuk kepada struktur MyError dalam baris di bawah.

Saya juga faham mengapa saya boleh menegaskan ralat dalam fungsi utama kembali ke penunjuk.

Penyelesaian

Untuk memahami pengendalian ralat tradisional dalam Go, anda harus terlebih dahulu memahami cara antara muka dalam bahasa berfungsi. Terdapat dua perkara yang perlu diingat apabila bercakap tentang antara muka Go:

  1. Antara muka dalam Go mentakrifkan satu set kaedah (bermula dengan Go1.18 juga merupakan satu set jenis). Di sebalik tabir, antara muka Go mengandungi dua elemen, jenis T 和值 VV 始终是具体类型,例如 intstruct atau penunjuk, bukannya antara muka itu sendiri.

  2. Tiada kata kunci implements dalam Go. Jenis Go memenuhi antara muka ini dengan melaksanakan kaedahnya. Ini dipanggil implisitpelaksanaan.

Ralat pengendalian

Go mentakrifkan jenis error terbina dalam, yang hanya antara muka:

type error interface {
    Error() string
}

Malah, tiada apa yang istimewa mengenainya, kecuali ia adalah jenis yang diisytiharkan secara global. Jenis ini biasanya digunakan untuk pengendalian ralat.

Ambil contoh anda:

func myFunction() (int, error) {
    return 0, &MyError{"my error message", 0}
}

func main() {
    var _, err = myFunction()
    if e, ok := err.(*MyError); ok {
        fmt.Printf("Error is %s: %d\n", e.message, e.Offset)
    }
}

Hubungan antara penuding kepada MyError dan MyError 的指针和 error 接口之间的关系发生在幕后,您不需要显式返回 *error 即可从 MyError 值引用 error antara muka berlaku di sebalik tabir, anda tidak perlu memulangkan *error secara eksplisit untuk mendapatkan nilai daripada MyError Rujukan (Malah, anda hampir tidak pernah memerlukan penunjuk ke antara muka

).

myFunction 后,error 值将保存以下元组 (V=&MyError{message: "my error message", Offset: 0}, T=*MyError),其中 V 是它的值保持,T 是值 VSelepas mengembalikan myFunction, nilai

akan menyimpan tuple berikut (V=&MyError{message: "my error message", Offset: 0}, T=*MyError) , Di mana V ialah pegangan nilainya dan T ialah jenis nilai V.

e, ok := err.(*MyError) 是: err 值(哪种类型是 error 接口)是否将类型 *MyError 作为其底层 T?如果是这样,则 ok 将是 true,并且 e 将接收其底层 V&MyError{message: "我的错误消息", Offset: 0}Kerana Go membolehkan anda menaip penegasan pada nilai antara muka. Pada asasnya, perkara yang anda tanya tentang operasi Go e, ok := err.(*MyError) ialah: sama ada nilai err (yang jenis ialah antara muka

) akan menjadi jenis *MyError sebagai asasnya T? Jika ya, maka ok akan menjadi true dan e akan menerima nilai V asasnya &MyError {message : "Mesej ralat saya", Offset: 0}.

Notanil: Sila layan nilai ralat ​​dengan berhati-hati, kerana mereka mungkin tidak sentiasa berkelakuan seperti yang diharapkan

disebabkan oleh nuansa antara muka. 🎜

Atas ialah kandungan terperinci Mengapakah Go mengembalikan penunjuk kepada pembalut ralat tetapi mengisytiharkannya dengan "ralat" dan bukannya "* ralat". Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam