Siirry parhaisiin käytäntöihin - virheiden käsittely

Tämä on ensimmäinen artikkeli oppituntisarjasta, jonka olen oppinut parin vuoden aikana, kun olen työskennellyt Go: n kanssa tuotannossa. Meillä on lukuisia Go-palveluita tuotannossa Saltside Technologiesissa (psst, palkan useita tehtäviä Bangaloressa Saltsidelle) ja ylläpidän myös omaa yritystäni, jossa Go on olennainen osa.

Aiomme kattaa suuren määrän aiheita, suuria ja pieniä.

Ensimmäinen aihe, jonka halusin kattaa tässä sarjassa, on virheiden käsittely. Se aiheuttaa usein hämmennystä ja ärsytystä uusille Go-kehittäjille.

Jotkut tausta - virherajapinta

Olemme vain samalla sivulla. Kuten ehkä tiedät, että Go-virhe on yksinkertaisesti mikä tahansa, joka toteuttaa virherajapinnan. Näyttää siltä, ​​mitä rajapinnan määritelmä näyttää:

tyyppivirherajapinta {
    Virhe () merkkijono
}

Joten mitä tahansa, joka toteuttaa Virhe () -merkkijono-menetelmän, voidaan käyttää virheenä.

Virheiden tarkistaminen

Virherakenteiden käyttäminen ja tyyppitarkastus

Kun aloin kirjoittaa Goa, tein usein merkkijonovertailuja virheilmoituksista nähdäkseni, mikä virhetyyppi oli (kyllä, kiusallista ajatella, mutta joskus sinun on katsottava taaksepäin mennäksesi eteenpäin).

Parempi tapa on käyttää virhetyyppejä. Joten voit (tietysti) luoda rakenteita, jotka toteuttavat virherajapinnan, ja tehdä sitten tyyppivertailu kytkinlausekkeessa.

Tässä on esimerkki virheiden toteutuksesta.

tyyppi ErrZeroDivision-rakenne {
    viestin merkkijono
}
func NewErrZeroDivision (viestijono) * ErrZeroDivision {
    paluu & ErrZeroDivision {
        viesti: viesti,
    }
}
func (e * ErrZeroDivision) -virhe () merkkijono {
    palauta sähköposti
}

Nyt tätä virhettä voidaan käyttää näin.

func main () {
    tulos, virhe: = jaa (1,0, 0,0)
    jos virhe! = nolla {
        kytkinvirhe (tyyppi) {
        tapaus * ErrZeroDivision:
            fmt.Println (err.Error ())
        oletus:
            fmt.Println ("Mitä h * juuri tapahtui?")
        }
    }
    fmt.Println (tulos)
}
func-jako (a, b float64) (float64, virhe) {
    jos b == 0,0 {
        tuotto 0.0, NewErrZeroDivision ("Ei voi jakaa nollalla")
    }
    palauta a / b, nolla
}

Tässä on Go Play -linkki täydelliseen esimerkkiin. Huomaa kytkinvirhe (tyyppi) -malli, jonka avulla on mahdollista tarkistaa erilaisia ​​virhetyyppejä kuin jotain muuta (kuten merkkijonovertailu tai jotain vastaavaa).

Virhepaketin käyttö ja suora vertailu

Edellä esitetty lähestymistapa voidaan vaihtoehtoisesti käsitellä virhepaketin avulla. Tämä lähestymistapa on suositeltava virheiden tarkistamiselle paketissa, jossa tarvitset nopean virheesityksen.

var errNotFound = virhe.New ("Tuotetta ei löydy")
func main () {
    err: = getItem (123) // Tämä heittää errNotFound
    jos virhe! = nolla {
        kytkinvirhe {
        case errNotFound:
            log.Println ("Pyydettyä tuotetta ei löydy")
        oletus:
            log.Println ("Tapahtui tuntematon virhe")
        }
    }
}

Tämä lähestymistapa ei ole yhtä hyvä, kun tarvitset monimutkaisempia virhekohteita esimerkiksi virhekoodit jne. Tässä tapauksessa sinun tulee luoda oma tyyppi, joka toteuttaa virherajapinnan.

Välitön virheiden käsittely

Joskus törmännyt koodiin kuten alla (mutta yleensä enemmän fluffia ympärillä ..):

func esimerkki1 () virhe {
    virhe: = call1 ()
    palautusvirhe
}

Asia on tässä, että virhettä ei käsitellä heti. Tämä on hauras lähestymistapa, koska joku voi lisätä koodin err: = call1 () ja paluuvirheen väliin, mikä rikkoisi aikomuksen, koska se saattaa varjostaa ensimmäisen virheen. Kaksi vaihtoehtoista lähestymistapaa:

// Kutista palautus ja virhe.
func esimerkki2 () virhe {
    vastapuhelu1 ()
}
// Suorita nimenomainen virheiden käsittely heti puhelun jälkeen.
func esimerkki3 () virhe {
    virhe: = call1 ()
    jos virhe! = nolla {
        palautusvirhe
    }
    palauta nolla
}

Molemmat edellä esitetyt lähestymistavat ovat minusta hyvin. He saavuttavat saman asian, mikä on; Jos jonkun täytyy lisätä jotain puhelun1 () jälkeen, hänen on huolehdittava virheiden käsittelystä.

Siinä kaikki tältä päivältä

Pysy kuulossa seuraavan artikkelin kanssa, joka koskee Go Best Practices -tapahtumaa. Mene vahvaksi :).

func main () {
    err: = readArticle ("Parhaat käytännöt - Virheiden käsittely")
    jos virhe! = nolla {
        ping ( "@ sebdah")
    }
}