Я пытался выдать ошибки в моей программе Golang, log.Fatal
но log.Fatal
не печатал строку, в которой log.Fatal
был запущен. Нет ли возможности получить доступ к номеру строки, которая называется log.Fatal? т.е. есть ли способ получить номер строки при выдаче ошибки?
Я пытался погуглить, но не знал, как это сделать. Лучшее, что я мог получить, - это распечатать трассировку стека , что, я думаю, хорошо, но может быть слишком много. Я также не хочу писать debug.PrintStack()
каждый раз, когда мне нужен номер строки, я просто удивлен, что нет встроенной функции для этого типа log.FatalStackTrace()
или чего-то, что не является костюмом.
Кроме того, причина, по которой я не хочу делать свои собственные средства отладки / обработки ошибок, заключается в том, что я не хочу, чтобы люди учились использовать мой специальный код обработки костюмов. Я просто хочу что-то стандартное, чтобы люди могли прочитать мой код позже и походить на
"А, хорошо, значит, он выдает ошибку и выполняет X ..."
Чем меньше людей узнают о моем коде, тем лучше :)
источник
Ответы:
Вы можете установить флаги либо в пользовательском Регистраторе, либо по умолчанию, чтобы включить
Llongfile
илиLshortfile
// to change the flags on the default logger log.SetFlags(log.LstdFlags | log.Lshortfile)
источник
var mylog = log.New(os.Stderr, "app: ", log.LstdFlags | log.Lshortfile)
.expected declaration, found 'INDENT' log
при попытке сделатьlog.SetFlags(log.LstdFlags | log.Lshortfile)
. Меня просто раздражает необходимость создавать для него переменную, почему не может бытьlog.Fatal("string", log.Flag)
. Но создание нового журнала переменных сработало. Стандартно ли создавать переменные журнала и прочее?func init() {}
Укороченная версия,
нет ничего напрямую встроенного, однако вы можете реализовать его с минимальной кривой обучения, используя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
источник
fn
Переменной присваивается отruntime.Caller()
фактически имя файла, а не функция отсчета. Я считаю fn функцией, а не именем файла .runtime
использования пакета. Очень полезно для отладки через журналы.Если вам нужна именно трассировка стека, взгляните на https://github.com/ztrue/tracerr
Я создал этот пакет, чтобы иметь как трассировку стека, так и исходные фрагменты, чтобы иметь возможность быстрее отлаживать и регистрировать ошибки с гораздо более подробной информацией.
Вот пример кода:
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) }
И вот результат:
источник