Go Best Practices - Hata işleme

Bu, Go yapımında çalıştığım birkaç yıl boyunca öğrendiğim bir dizi dersteki ilk makale. Saltside Technologies'de üretimde çok sayıda Go hizmeti veriyoruz (psst, Saltside için Bangalore'da birden fazla pozisyonda çalışıyorum) ve Go'nun ayrılmaz bir parçası olduğu kendi işimi de yürütüyorum.

Büyük ve küçük geniş bir konu yelpazesini ele alacağız.

Bu seride ele almak istediğim ilk konu hata yönetimi. Sık sık yeni Go geliştiricileri için karışıklık ve sıkıntıya neden oluyor.

Bazı arka plan - Hata arayüzü

Sadece aynı sayfadayız. Go'daki bir hatayı bildiğiniz gibi, hata arayüzünü uygulayan herhangi bir şeydir. Arayüz tanımı şöyle görünür:

hata arabirimi {}
    Hata () dizesi
}

Bu nedenle, Error () string yöntemini uygulayan herhangi bir şey, hata olarak kullanılabilir.

Hataları kontrol etme

Hata yapılarını kullanma ve tip kontrolü

Go yazmaya başladığımda, hata türünün ne olduğunu görmek için genellikle hata mesajlarının dize karşılaştırmalarını yaptım (evet, düşünmekten utanç verici ama bazen ileriye bakmak için tekrar bakmanız gerekir).

Hata türlerini kullanmak daha iyi bir yaklaşımdır. Böylece (elbette) hata arayüzünü uygulayan yapılar oluşturabilir ve daha sonra bir switch ifadesinde karşılaştırma yazabilirsiniz.

İşte örnek bir hata uygulaması.

ErrZeroDivision yapı tipi {
    mesaj dizesi
}
func NewErrZeroDivision (ileti dizesi) * ErrZeroDivision {
    dönüş & ErrZeroDivision {
        mesaj: mesaj
    }
}
func (e * ErrZeroDivision) Hata () string {
    mesaj gönder
}

Şimdi bu hata bu şekilde kullanılabilir.

func main () {
    sonuç, hata: = bölme (1.0, 0.0)
    eğer err! = nil {
        anahtar err. (tür) {
        vaka * ErrZeroDivision:
            fmt.Println (err.Error ())
        varsayılan:
            fmt.Println ("Ne h * yeni oldu?")
        }
    }
    fmt.Println (sonuç)
}
func bölme (a, b float64) (float64, hata) {
    eğer b == 0.0 {
        0,0 döndürür, NewErrZeroDivision ("Sıfırla bölünemez")
    }
    a / b döndür, sıfır
}

İşte tam örnek için Go Play bağlantısı. Anahtar hatası (tip) desenine dikkat edin, bu da başka bir şey yerine farklı hata türlerini kontrol etmeyi mümkün kılar (dize karşılaştırması veya benzeri bir şey gibi).

Hata paketini kullanma ve doğrudan karşılaştırma

Yukarıdaki yaklaşım alternatif olarak hata paketi kullanılarak ele alınabilir. Bu yaklaşım, hızlı bir hata sunumuna ihtiyaç duyduğunuz paket içindeki hata kontrolleri için önerilir.

var errNotFound = errors.New ("Öğe bulunamadı")
func main () {
    err: = getItem (123) // Bu, errNotFound değerini attı
    eğer err! = nil {
        anahtarını değiştir {
        case errNotFound:
            log.Println ("İstenen öğe bulunamadı")
        varsayılan:
            log.Println ("Bilinmeyen hata oluştu")
        }
    }
}

Örneğin, daha karmaşık hata nesnelerine ihtiyaç duyduğunuzda bu yaklaşım daha az iyidir. hata kodları vb. Bu durumda, hata arabirimini uygulayan kendi türünüzü oluşturmalısınız.

Acil hata işleme

Bazen aşağıdaki gibi bir kodla karşılaşıyorum (ancak genellikle daha çok kabarık oluyor ..):

func example1 () hatası {
    err: = call1 ()
    geri dönüş
}

Buradaki nokta, err'in hemen ele alınmamasıdır. Bu, kırılgan bir yaklaşımdır, çünkü birisi, err: = call1 () ve return err arasına kod ekleyebildiğinden, ilk hatayı gölgeleyebilir. İki alternatif yaklaşım:

// Dönüşü ve hatayı daralt.
func example2 () hatası {
    call1 döndür ()
}
// Görüşten hemen sonra açık bir hata yapıyorsunuz.
func example3 () hatası {
    err: = call1 ()
    eğer err! = nil {
        geri dönüş
    }
    geri dönüş
}

Yukarıdaki yaklaşımların her ikisi de benimle iyi. Aynı şeyi başarırlar ki; Eğer call1 () fonksiyonundan sonra bir şeyler eklemek gerekirse, hata işlemeye dikkat etmeleri gerekir.

Hepsi bugün için

Go Best Practices ile ilgili bir sonraki makale için bizi izlemeye devam edin. Güçlü ol :).

func main () {
    err: = readArticle ("En İyi Uygulamalara Git - Hata işleme")
    eğer err! = nil {
        Ping ( "@ sebdah")
    }
}