Saya mencoba membuang kesalahan dalam program Golang saya dengan log.Fatal
tetapi, log.Fatal
tidak juga mencetak baris di mana log.Fatal
itu dijalankan. Apakah tidak ada cara untuk mendapatkan akses ke nomor baris yang disebut log.Fatal? yaitu apakah ada cara untuk mendapatkan nomor baris saat melakukan kesalahan?
Saya mencoba mencari ini di Google tetapi tidak yakin caranya. Hal terbaik yang bisa saya dapatkan adalah mencetak jejak tumpukan , yang menurut saya bagus tapi mungkin terlalu banyak. Saya juga tidak ingin menulis debug.PrintStack()
setiap kali saya membutuhkan nomor baris, saya hanya terkejut tidak ada fungsi bawaan untuk ini log.FatalStackTrace()
atau sesuatu yang bukan kostum.
Juga, alasan saya tidak ingin membuat debugging / error handling saya sendiri adalah karena saya tidak ingin orang lain harus belajar bagaimana menggunakan kode penanganan kostum khusus saya. Saya hanya ingin sesuatu yang standar di mana orang dapat membaca kode saya nanti dan menjadi seperti
"ah ok, jadi itu membuat kesalahan dan melakukan X ..."
Semakin sedikit orang yang harus mempelajari kode saya, semakin baik :)
sumber
Jawaban:
Anda dapat mengatur Bendera di Logger kustom, atau default untuk menyertakan
Llongfile
atauLshortfile
// to change the flags on the default logger log.SetFlags(log.LstdFlags | log.Lshortfile)
sumber
var mylog = log.New(os.Stderr, "app: ", log.LstdFlags | log.Lshortfile)
.expected declaration, found 'INDENT' log
ketika saya mencoba melakukannyalog.SetFlags(log.LstdFlags | log.Lshortfile)
. Itu hanya mengganggu saya harus membuat variabel untuk itu, mengapa tidak adalog.Fatal("string", log.Flag)
. Tetapi membuat log variabel baru berhasil. Apakah itu hal standar untuk membuat variabel log dan semacamnya?func init() {}
Versi pendek,
tidak ada yang langsung terpasang, namun Anda dapat menerapkannya dengan kurva pembelajaran minimal menggunakanruntime.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
sumber
fn
variabel ditugaskan dariruntime.Caller()
sebenarnya nama file, bukan referensi fungsi. Saya menganggap fn sebagai fungsi, bukan nama file .runtime
penggunaan paket. Sangat membantu untuk debugging melalui log.Jika Anda membutuhkan pelacakan tumpukan yang tepat, lihat di https://github.com/ztrue/tracerr
Saya membuat paket ini agar memiliki pelacakan tumpukan dan fragmen sumber agar dapat men-debug lebih cepat dan mencatat kesalahan dengan lebih banyak detail.
Berikut adalah contoh kode:
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) }
Dan inilah hasilnya:
sumber