Warum gibt Go einen Zeiger auf einen Fehler-Wrapper zurück, deklariert ihn aber mit „error' statt „*error'?

WBOY
Freigeben: 2024-02-09 22:40:10
nach vorne
556 Leute haben es durchsucht

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

Warum gibt Go einen Zeiger auf einen Fehler-Wrapper zurück, deklariert ihn aber mit „error“ statt „error“? Dies ist ein häufiges Problem, auf das viele Go-Sprachentwickler stoßen. Einfach ausgedrückt besteht die Art und Weise, wie Go Fehler zurückgibt, darin, die Verwendung und den Umgang mit Fehlern zu vereinfachen. In Go ist ein Fehler ein Schnittstellentyp, der über eine Error()-Methode verfügt, die eine Fehlermeldung zurückgibt. Wenn eine Funktion daher einen Fehler zurückgibt, gibt sie tatsächlich einen Zeiger auf eine Struktur zurück, die die Methode Error() implementiert. Dieses Design macht die Fehlerbehandlung präziser und flexibler und reduziert Code-Redundanz und -Komplexität. Auch wenn die Rückgabe eines Zeigers seltsam erscheinen mag, dient sie eigentlich dazu, eine bessere Fehlerbehandlung zu ermöglichen.

Frageninhalt

Ich lerne die Go-Sprache mit Java-Hintergrund.

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)
    }
}
Nach dem Login kopieren

Im obigen Code verstehe ich nicht, warum der Fehlertyp von myFunction „error“ statt „*error“ ist? Ich gebe in der folgenden Zeile eindeutig einen Zeiger auf die MyError-Struktur zurück.

Ich verstehe auch, warum ich den Fehler in der Hauptfunktion auf den Zeiger zurückführen kann.

Workaround

Um die traditionelle Fehlerbehandlung in Go zu verstehen, sollten Sie zunächst verstehen, wie Schnittstellen in der Sprache funktionieren. Wenn man über Go-Schnittstellen spricht, sind zwei Dinge zu beachten:

  1. Eine Schnittstelle in Go definiert eine Reihe von Methoden (beginnend mit Go1.18 ist auch eine Reihe von Typen). Hinter den Kulissen enthalten Go-Schnittstellen zwei Elemente, Typen T 和值 VV 始终是具体类型,例如 intstruct oder Zeiger, und nicht die Schnittstelle selbst.

  2. Es gibt kein implements Schlüsselwort in Go. Go-Typen erfüllen diese Schnittstelle, indem sie ihre Methoden implementieren. Dies wird als „implizite“ Implementierung bezeichnet.

  3. Fehlerbehandlung

Go definiert einen integrierten

-Typ, der lediglich eine Schnittstelle ist:

type error interface {
    Error() string
}
Nach dem Login kopieren
errorTatsächlich gibt es nichts Besonderes daran, außer dass es sich um einen globalen

vordeklarierten Typ

handelt. Dieser Typ wird typischerweise zur Fehlerbehandlung verwendet. Nehmen Sie Ihr Beispiel:

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)
    }
}
Nach dem Login kopieren

Die Beziehung zwischen dem Zeiger auf MyError und der

Schnittstelle geschieht im Hintergrund. Sie müssen *error nicht explizit zurückgeben, um den Wert von MyError zu erhalten Referenz

(Tatsächlich benötigen Sie MyError 的指针和 error 接口之间的关系发生在幕后,您不需要显式返回 *error 即可从 MyError 值引用 error fast nie einen Zeiger auf eine Schnittstelle ).

Nach der Rückgabe von myFunction speichert der

-Wert das folgende Tupel (V=&MyError{message: "my error message", Offset: 0}, T=*MyError) , wobei V sein Werthalt und T der Typ des Werts V ist. myFunction 后,error 值将保存以下元组 (V=&MyError{message: "my error message", Offset: 0}, T=*MyError),其中 V 是它的值保持,T 是值 V

Weil Go es Ihnen ermöglicht, Aussagen zu Schnittstellenwerten einzugeben. Was Sie über die Go-Operation e, ok := err.(*MyError) im Grunde fragen, ist: ob der err-Wert (welcher Typ ist die

-Schnittstelle) wird vom Typ *MyError als zugrunde liegender T sein? Wenn ja, dann ist ok true und e erhält den zugrunde liegenden V-Wert &MyError {message : „Meine Fehlermeldung“, Offset: 0}. e, ok := err.(*MyError) 是: err 值(哪种类型是 error 接口)是否将类型 *MyError 作为其底层 T?如果是这样,则 ok 将是 true,并且 e 将接收其底层 V&MyError{message: "我的错误消息", Offset: 0}

Hinweis: Bitte behandeln Sie Fehlerwerte mit Vorsicht, nil da sie sich aufgrund von Schnittstellennuancen möglicherweise nicht immer wie erwartet verhalten .

Das obige ist der detaillierte Inhalt vonWarum gibt Go einen Zeiger auf einen Fehler-Wrapper zurück, deklariert ihn aber mit „error' statt „*error'?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!