Rumah >pembangunan bahagian belakang >Golang >Mengapakah Go mengembalikan penunjuk kepada pembalut ralat tetapi mengisytiharkannya dengan 'ralat' dan bukannya '* ralat'
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.
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.
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:
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
和值 V
。 V
始终是具体类型,例如 int
、struct
atau penunjuk, bukannya antara muka itu sendiri.
Tiada kata kunci implements
dalam Go. Jenis Go memenuhi antara muka ini dengan melaksanakan kaedahnya. Ini dipanggil implisitpelaksanaan.
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
是值 V
Selepas mengembalikan myFunction
, nilai
(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
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
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!