go使用errors.Wrapf()代替log.Error()方法示例
引言
介紹不同語(yǔ)言的錯(cuò)誤處理機(jī)制:
Musings about error handling mechanisms in programming languages
項(xiàng)目中 main調(diào)func1,func1調(diào)取func2...
這樣就會(huì)出現(xiàn)很多的 if err != nil { log.Printf()} , 在Kibana上查看時(shí)會(huì)搜到多條日志, 需要逐級(jí)定位, 確定錯(cuò)誤拋出的點(diǎn)
希望只有一條, 能清晰看到整個(gè)堆棧調(diào)用信息
使用log.xxxx方法
package main
import (
"fmt"
"log"
"strconv"
"time"
)
func init() {
log.SetFlags(log.Lshortfile | log.LstdFlags)
}
func main() {
str := "123a"
rs, err := func1(str)
if err != nil {
log.Printf("err is (%+v)\n", err)
return
}
fmt.Println("最終結(jié)果為:", rs)
}
func func1(str string) (int, error) {
b, err := func2()
if err != nil {
log.Printf("There is func11111, func2 err(%+v)\n", err)
}
if b == false {
strInt, err := strconv.Atoi(str)
if err != nil {
log.Printf("There is func11111, err(%+v)\n", err)
}
return strInt, err
}
return 0, nil
}
func func2() (bool, error) {
now := time.Now().Unix()
endTimeStr := "2021-08-06 20:00:0000"
endtime, err := time.ParseInLocation("2006-01-02 15:04:05", endTimeStr, time.Local)
if err != nil {
log.Printf("There is func22222, err(%+v)\n", err)
return false, err
}
if endtime.Unix() > now {
return true, nil
}
return false, nil
}執(zhí)行結(jié)果:
2021/06/07 21:52:56 vs.go:56: There is func22222, err(parsing time "2021-08-06 20:00:0000": extra text: "00")
2021/06/07 21:52:56 vs.go:33: There is func11111, func2 err(parsing time "2021-08-06 20:00:0000": extra text: "00")
2021/06/07 21:52:56 vs.go:40: There is func11111, err(strconv.Atoi: parsing "123a": invalid syntax)
2021/06/07 21:52:56 vs.go:20: err is (strconv.Atoi: parsing "123a": invalid syntax)
使用errors.Wrapf方法
package main
import (
"fmt"
"github.com/pkg/errors"
"strconv"
"time"
)
func main() {
str := "123a"
rs, err := func1(str)
if err != nil {
fmt.Printf("err: %+v\n", err)
//fmt.Println("err:", lastErr) //必須%+v才會(huì)打印完整堆棧信息,否則只打印錯(cuò)誤信息
return
}
fmt.Println("最終結(jié)果為:", rs)
}
func func1(str string) (int, error) {
b, err := func2()
if err != nil {
err = errors.Wrapf(err, "There is func11111, func2 err, b is(%b) \n", b)
}
if b == false {
var strInt int
strInt, err = strconv.Atoi(str)
if err != nil {
err = errors.Wrapf(err, "There is func11111,str is(%s)\n", str)
}
return strInt, err
}
return 0, nil
}
func func2() (bool, error) {
now := time.Now().Unix()
endTimeStr := "2021-08-06 20:00:0000"
endtime, err := time.ParseInLocation("2006-01-02 15:04:05", endTimeStr, time.Local)
if err != nil {
err = errors.Wrapf(err, "There is func22222,endTimeStr is(%s)\n", endTimeStr)
return false, err
}
if endtime.Unix() > now {
return true, nil
}
return false, nil
}執(zhí)行:
err: strconv.Atoi: parsing "123a": invalid syntax
There is func11111,str is(123a)
main.func1
/Users/fliter/go/src/shuang/llog/1.go:39
main.main
/Users/fliter/go/src/shuang/llog/1.go:13
runtime.main
/usr/local/Cellar/go/1.16.3/libexec/src/runtime/proc.go:225
runtime.goexit
/usr/local/Cellar/go/1.16.3/libexec/src/runtime/asm_amd64.s:1371
注意賦值這步, 必不可少!
有一個(gè)問題, 即對(duì)于f1調(diào)f2,f2調(diào)f3這種, 如果f3發(fā)生error, 可以逐級(jí)將error拋出.
但如果一個(gè)方法里有兩個(gè)error, 則第二條會(huì)覆蓋掉第一條,如上 err = errors.Wrapf(err, "There is func11111, func2 err, b is(%b) \n", b)這一條就被覆蓋了
// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
err = &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
}
return &withStack{
err,
callers(),
}
}func callers() *stack {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(3, pcs[:])
var st stack = pcs[0:n]
return &st
}// Callers fills the slice pc with the return program counters of function invocations
// on the calling goroutine's stack. The argument skip is the number of stack frames
// to skip before recording in pc, with 0 identifying the frame for Callers itself and
// 1 identifying the caller of Callers.
// It returns the number of entries written to pc.
//
// To translate these PCs into symbolic information such as function
// names and line numbers, use CallersFrames. CallersFrames accounts
// for inlined functions and adjusts the return program counters into
// call program counters. Iterating over the returned slice of PCs
// directly is discouraged, as is using FuncForPC on any of the
// returned PCs, since these cannot account for inlining or return
// program counter adjustment.
func Callers(skip int, pc []uintptr) int {
// runtime.callers uses pc.array==nil as a signal
// to print a stack trace. Pick off 0-length pc here
// so that we don't let a nil pc slice get to it.
if len(pc) == 0 {
return 0
}
return callers(skip, pc)
}func callers(skip int, pcbuf []uintptr) int {
sp := getcallersp()
pc := getcallerpc()
gp := getg()
var n int
systemstack(func() {
n = gentraceback(pc, sp, 0, gp, skip, &pcbuf[0], len(pcbuf), nil, nil, 0)
})
return n
}
參考:
以上就是go使用errors.Wrapf()代替log.Error()方法示例的詳細(xì)內(nèi)容,更多關(guān)于go errors.Wrapf log.Error的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解如何使用Golang實(shí)現(xiàn)Cron定時(shí)任務(wù)
定時(shí)任務(wù)是許多應(yīng)用程序中常見的一種需求,它們可以用于執(zhí)行定期的清理任務(wù),發(fā)送通知,生成報(bào)告等,在這篇博客中,我們將介紹如何在Go語(yǔ)言中使用robfig/cron包來(lái)實(shí)現(xiàn)Cron定時(shí)任務(wù),需要的朋友可以參考下2024-04-04
關(guān)于golang高并發(fā)的實(shí)現(xiàn)與注意事項(xiàng)說(shuō)明
這篇文章主要介紹了關(guān)于golang高并發(fā)的實(shí)現(xiàn)與注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05
go 類型轉(zhuǎn)換方式(interface 類型的轉(zhuǎn)換)
這篇文章主要介紹了go 類型轉(zhuǎn)換方式(interface 類型的轉(zhuǎn)換),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05
更高效的GoLevelDB:shardingdb實(shí)現(xiàn)分片和并發(fā)讀寫操作
這篇文章主要介紹了更高效的GoLevelDB:shardingdb實(shí)現(xiàn)分片和并發(fā)讀寫操作的相關(guān)資料,需要的朋友可以參考下2023-09-09
Golang中的信號(hào)(Signal)機(jī)制詳解
Signal 是一種操作系統(tǒng)級(jí)別的事件通知機(jī)制,進(jìn)程可以響應(yīng)特定的系統(tǒng)信號(hào),這些信號(hào)用于指示進(jìn)程執(zhí)行特定的操作,如程序終止、掛起、恢復(fù)等,Golang 的標(biāo)準(zhǔn)庫(kù) os/signal 提供了對(duì)信號(hào)處理的支持,本文將詳細(xì)講解 Golang 是如何處理和響應(yīng)系統(tǒng)信號(hào)的,需要的朋友可以參考下2024-01-01
Golang語(yǔ)言學(xué)習(xí)拿捏Go反射示例教程
這篇文章主要為大家介紹了Golang語(yǔ)言中Go反射示例的教程,教你拿捏Go反射,再也不用被Go反射折磨,有需要的朋友可以共同學(xué)習(xí)參考下2021-11-11

