Az önce adlandırdığı hatanın satır numarasını yazdıracak bir Golang programını nasıl edinebilirsiniz?


96

Golang programımda ile hatalar atmaya çalışıyordum log.Fatalama çalıştırıldığı log.Fatalsatırı da yazdırmıyor log.Fatal. Log.Fatal denen satır numarasına erişmenin bir yolu yok mu? Yani bir hata atarken satır numarasını almanın bir yolu var mı?

Bunu google'da aramaya çalışıyordum ama nasıl olduğundan emin değildim. Elde edebileceğim en iyi şey , yığın izini yazdırmaktı, sanırım bu iyi ama biraz fazla olabilir. Ayrıca debug.PrintStack()her satır numarasına ihtiyacım olduğunda yazmak istemiyorum , sadece bunun gibi log.FatalStackTrace()veya kostüm olmayan bir şey için yerleşik bir işlev olmadığına şaşırdım .

Ayrıca, kendi hata ayıklama / hata işleme işimi yapmak istemememin nedeni, insanların özel kostüm işleme kodumu nasıl kullanacaklarını öğrenmek zorunda kalmalarını istemememdir. İnsanların daha sonra kodumu okuyabileceği ve

"ah tamam, bu yüzden bir hata veriyor ve X yapıyor ..."

Ne kadar az insan kodum hakkında bilgi sahibi olursa o kadar iyi :)



Satır numaralarını yazdırdığınız an bu, kodunuza dalmak zorunda kalacağım anlamına gelir, bu nedenle "Ne kadar az insan kodumu öğrenirse o kadar iyi" burada tartışmalıdır. Yapmanız gereken, açık ve kısa hatalar yapmaktır.
Wessie

Yanıtlar:


124

Bayrakları özel bir Kaydedici üzerinde veya varsayılan olarak dahil etmek LlongfileveyaLshortfile

// to change the flags on the default logger
log.SetFlags(log.LstdFlags | log.Lshortfile)

Yani, bunun işe yaraması için bunu yalnızca paket dosyalarından birinin en üstüne ayarlamam gerekiyor ve o paket için tüm dosyalarım için kullanılabilir mi?
Pinokyo

4
Evet, özel bir günlük kullanıyorsanız, istediğiniz gibi kullanabilirsiniz var mylog = log.New(os.Stderr, "app: ", log.LstdFlags | log.Lshortfile).
OneOfOne

gerçekten bir değişken oluşturmam gerekiyor mu? Go dosyamın en üstünde log.SetFlags (log.LstdFlags | log.Lshortfile) yapamam? Bir hata alıyorum: expected declaration, found 'INDENT' logyapmaya çalıştığımda log.SetFlags(log.LstdFlags | log.Lshortfile). Onun için bir değişken yaratmak zorunda olmak beni rahatsız ediyor, neden bir log.Fatal("string", log.Flag). Ancak yeni bir değişken günlük oluşturmak işe yaradı. Günlük değişkenleri ve benzeri şeyler oluşturmak standart bir şey mi?
Pinokyo

3
@Pinocchio: Bu hata, geçerli Go olmadığı için, en üst düzeyde çıplak bir işlev çağrısı yapamazsınız. Bunu init () veya başka bir giriş noktasına koyun.
JimB

5
koymalısınfunc init() {}
OneOfOne

94

Kısa versiyon, doğrudan yerleşik hiçbir şey yokancak bunu kullanarak minimum bir öğrenme eğrisi ile uygulayabilirsiniz. runtime.Caller

func HandleError(err error) (b bool) {
    if err != nil {
        // notice that we're using 1, so it will actually log where
        // the error happened, 0 = this function, we don't want that.
        _, fn, line, _ := runtime.Caller(1)
        log.Printf("[error] %s:%d %v", fn, line, err)
        b = true
    }
    return
}

//this logs the function name as well.
func FancyHandleError(err error) (b bool) {
    if err != nil {
        // notice that we're using 1, so it will actually log the where
        // the error happened, 0 = this function, we don't want that.
        pc, fn, line, _ := runtime.Caller(1)

        log.Printf("[error] in %s[%s:%d] %v", runtime.FuncForPC(pc).Name(), fn, line, err)
        b = true
    }
    return
}

func main() {
    if FancyHandleError(fmt.Errorf("it's the end of the world")) {
        log.Print("stuff")
    }
}

playground


11
Zaten verilen cevap sorunu düzgün bir şekilde düzeltirken, çözümünüz beni harika bir şeyin varlığı konusunda uyardı - çalışma zamanı paketi! Lovely stuff :) golang.org/pkg/runtime
Gwyneth Llewelyn

fnAtanmış değişken runtime.Caller()aslında dosyaya değil, bir fonksiyon referans adıdır. Fn'yi dosya adı değil, işlev olarak düşünüyorum .
2019,

1
Harika! Teşekkürler. Bu, runtimepaket kullanımına harika bir örnektir . Günlüklerle hata ayıklamak için çok yararlıdır.
18augst

2

Tam olarak bir yığın izlemesine ihtiyacınız varsa, https://github.com/ztrue/tracerr adresine bir göz atın.

Bu paketi hem yığın izleme hem de kaynak parçalarına sahip olmak için daha hızlı hata ayıklayabilmek ve hataları daha fazla ayrıntıyla günlüğe kaydedebilmek için oluşturdum.

İşte bir kod örneği:

package main

import (
    "io/ioutil"
    "github.com/ztrue/tracerr"
)

func main() {
    if err := read(); err != nil {
        tracerr.PrintSourceColor(err)
    }
}

func read() error {
    return readNonExistent()
}

func readNonExistent() error {
    _, err := ioutil.ReadFile("/tmp/non_existent_file")
    // Add stack trace to existing error, no matter if it's nil.
    return tracerr.Wrap(err)
}

Ve işte çıktı: golang hatası yığın izleme

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.