Zoeken…


Invoering

In Go worden onverwachte situaties behandeld met behulp van fouten , geen uitzonderingen. Deze benadering lijkt meer op die van C, met behulp van errno, dan op die van Java of andere objectgeoriënteerde talen, met hun try / catch-blokken. Een fout is echter geen geheel getal maar een interface.

Een functie die mogelijk mislukt, retourneert meestal een fout als de laatste retourwaarde. Als deze fout niet nul is , is er iets misgegaan en moet de beller van de functie dienovereenkomstig actie ondernemen.

Opmerkingen

Merk op hoe in Go u niet een fout te verhogen. In plaats daarvan retourneert u een fout in geval van mislukking.

Als een functie kan mislukken, is de laatst geretourneerde waarde meestal een error .

// This method doesn't fail
func DoSomethingSafe() {
}

// This method can fail
func DoSomething() (error) {
}

// This method can fail and, when it succeeds,
// it returns a string.
func DoAndReturnSomething() (string, error) {
}

Een foutwaarde maken

De eenvoudigste manier om een fout te maken is door het errors te gebruiken.

errors.New("this is an error")

Als u extra informatie aan een fout wilt toevoegen, biedt het fmt pakket ook een handige methode voor het maken van fouten:

var f float64
fmt.Errorf("error with some additional information: %g", f)

Hier is een volledig voorbeeld, waarbij de fout wordt geretourneerd door een functie:

package main

import (
    "errors"
    "fmt"
)

var ErrThreeNotFound = errors.New("error 3 is not found")

func main() {
    fmt.Println(DoSomething(1)) // succeeds! returns nil
    fmt.Println(DoSomething(2)) // returns a specific error message
    fmt.Println(DoSomething(3)) // returns an error variable
    fmt.Println(DoSomething(4)) // returns a simple error message
}

func DoSomething(someID int) error {
    switch someID {
    case 3:
        return ErrThreeNotFound
    case 2:
        return fmt.Errorf("this is an error with extra info: %d", someID)
    case 1:
        return nil
    }

    return errors.New("this is an error")
}

Open in Speeltuin

Een aangepast fouttype maken

In Go wordt een fout weergegeven door elke waarde die zichzelf als tekenreeks kan beschrijven. Elk type dat de ingebouwde error implementeert, is een fout.

// The error interface is represented by a single
// Error() method, that returns a string representation of the error
type error interface {
    Error() string
}

In het volgende voorbeeld wordt getoond hoe u een nieuw fouttype definieert met een letterlijke samengestelde tekenreeks.

// Define AuthorizationError as composite literal
type AuthorizationError string

// Implement the error interface
// In this case, I simply return the underlying string
func (e AuthorizationError) Error() string {
    return string(e)
}

Ik kan nu mijn aangepaste fouttype als fout gebruiken:

package main

import (
    "fmt"
)

// Define AuthorizationError as composite literal
type AuthorizationError string

// Implement the error interface
// In this case, I simply return the underlying string
func (e AuthorizationError) Error() string {
    return string(e)
}

func main() {
    fmt.Println(DoSomething(1)) // succeeds! returns nil
    fmt.Println(DoSomething(2)) // returns an error message
}

func DoSomething(someID int) error {
    if someID != 1 {
        return AuthorizationError("Action not allowed!")
    }

    // do something here

    // return a nil error if the execution succeeded
    return nil
}

Retourneert een fout

In Ga je niet een fout te verhogen. In plaats daarvan retourneert u een error in geval van een storing.

// This method can fail
func DoSomething() error {
    // functionThatReportsOK is a side-effecting function that reports its
    // state as a boolean. NOTE: this is not a good practice, so this example
    // turns the boolean value into an error. Normally, you'd rewrite this
    // function if it is under your control.
    if ok := functionThatReportsOK(); !ok {
        return errors.New("functionThatReportsSuccess returned a non-ok state")
    }

    // The method succeeded. You still have to return an error
    // to properly obey to the method signature.
    // But in this case you return a nil error.
    return nil
}

Als de methode meerdere waarden retourneert (en de uitvoering kan mislukken), is de standaardconventie dat de fout als laatste argument wordt geretourneerd.

// This method can fail and, when it succeeds,
// it returns a string.
func DoAndReturnSomething() (string, error) {
    if os.Getenv("ERROR") == "1" {
        return "", errors.New("The method failed")
    }

    s := "Success!"

    // The method succeeded.
    return s, nil
}

result, err := DoAndReturnSomething()
if err != nil {
    panic(err)
}

Verwerking van een fout

In Go kunnen fouten worden geretourneerd vanuit een functieaanroep. De conventie is dat als een methode kan mislukken, het laatst geretourneerde argument een error .

func DoAndReturnSomething() (string, error) {
    if os.Getenv("ERROR") == "1" {
        return "", errors.New("The method failed")
    }

    // The method succeeded.
    return "Success!", nil
}

U gebruikt meerdere variabele toewijzingen om te controleren of de methode is mislukt.

result, err := DoAndReturnSomething()
if err != nil {
    panic(err)
}

// This is executed only if the method didn't return an error
fmt.Println(result)

Als u niet geïnteresseerd bent in de fout, kunt u deze gewoon negeren door deze toe te wijzen aan _ .

result, _ := DoAndReturnSomething()
fmt.Println(result)

Natuurlijk kan het negeren van een fout ernstige gevolgen hebben. Daarom wordt dit over het algemeen niet aanbevolen.

Als u meerdere methodeaanroepen hebt en een of meer methoden in de keten een fout kunnen retourneren, moet u de fout doorgeven naar het eerste niveau dat het aankan.

func Foo() error {
    return errors.New("I failed!")    
}

func Bar() (string, error) {
    err := Foo()
    if err != nil {
        return "", err
    }

    return "I succeeded", nil
}

func Baz() (string, string, error) {
    res, err := Bar()
    if err != nil {
        return "", "", err
    }

    return "Foo", "Bar", nil
}

Herstellen van paniek

Een veel voorkomende fout is om een segment te declareren en er indexen om aan te vragen zonder het te initialiseren, wat leidt tot een paniek "index buiten bereik". De volgende code legt uit hoe u kunt herstellen van de paniek zonder het programma te verlaten, wat normaal is voor een paniek. In de meeste situaties is het retourneren van een fout op deze manier in plaats van het programma in paniek te verlaten alleen nuttig voor ontwikkelings- of testdoeleinden.

type Foo struct {
    Is []int
}

func main() {
    fp := &Foo{}
    if err := fp.Panic(); err != nil {
        fmt.Printf("Error: %v", err)
    } 
    fmt.Println("ok")
}

func (fp *Foo) Panic() (err error) {
    defer PanicRecovery(&err)
    fp.Is[0] = 5
    return nil
}

func PanicRecovery(err *error) {

    if r := recover(); r != nil {
        if _, ok := r.(runtime.Error); ok {
             //fmt.Println("Panicing")
             //panic(r)
             *err = r.(error) 
        } else {
            *err = r.(error)
        }
    }
}

Het gebruik van een afzonderlijke functie (in plaats van sluiting) maakt het mogelijk dezelfde functie opnieuw te gebruiken in andere paniekgevoelige functies.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow