欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go使用errors.Wrapf()代替log.Error()方法示例

 更新時間:2023年08月31日 11:02:46   作者:好文收藏  
這篇文章主要為大家介紹了go使用errors.Wrapf()代替log.Error()的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

介紹不同語言的錯誤處理機(jī)制:

Error handling patterns

Musings about error handling mechanisms in programming languages

項目中 main調(diào)func1,func1調(diào)取func2...

這樣就會出現(xiàn)很多的 if err != nil { log.Printf()} , 在Kibana上查看時會搜到多條日志, 需要逐級定位, 確定錯誤拋出的點

希望只有一條, 能清晰看到整個堆棧調(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才會打印完整堆棧信息,否則只打印錯誤信息
        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

注意賦值這步, 必不可少!

有一個問題, 即對于f1調(diào)f2,f2調(diào)f3這種, 如果f3發(fā)生error, 可以逐級將error拋出.
但如果一個方法里有兩個error, 則第二條會覆蓋掉第一條,如上 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
}

參考:

golang 打印error的堆棧信息

Go錯誤處理最佳實踐

以上就是go使用errors.Wrapf()代替log.Error()方法示例的詳細(xì)內(nèi)容,更多關(guān)于go errors.Wrapf log.Error的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解如何使用Golang實現(xiàn)Cron定時任務(wù)

    詳解如何使用Golang實現(xiàn)Cron定時任務(wù)

    定時任務(wù)是許多應(yīng)用程序中常見的一種需求,它們可以用于執(zhí)行定期的清理任務(wù),發(fā)送通知,生成報告等,在這篇博客中,我們將介紹如何在Go語言中使用robfig/cron包來實現(xiàn)Cron定時任務(wù),需要的朋友可以參考下
    2024-04-04
  • go語言制作的zip壓縮程序

    go語言制作的zip壓縮程序

    這篇文章主要介紹了go語言制作的zip壓縮程序,其主體思路是首先創(chuàng)建一個讀寫緩沖,然后用壓縮器包裝該緩沖,用Walk方法來將所有目錄下的文件寫入zip,有需要的小伙伴參考下。
    2015-03-03
  • Go?gin框架加載Html模板文件的方法

    Go?gin框架加載Html模板文件的方法

    這篇文章主要介紹了Go?gin框架加載Html模板文件的方法,Gin框架沒有內(nèi)置靜態(tài)文件服務(wù),但可以使用gin.Static或gin.StaticFS中間件來提供靜態(tài)文件服務(wù),文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下
    2024-03-03
  • Golang二維切片初始化的實現(xiàn)

    Golang二維切片初始化的實現(xiàn)

    這篇文章主要介紹了Golang二維切片初始化的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 關(guān)于golang高并發(fā)的實現(xiàn)與注意事項說明

    關(guān)于golang高并發(fā)的實現(xiàn)與注意事項說明

    這篇文章主要介紹了關(guān)于golang高并發(fā)的實現(xiàn)與注意事項說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • go 類型轉(zhuǎn)換方式(interface 類型的轉(zhuǎn)換)

    go 類型轉(zhuǎn)換方式(interface 類型的轉(zhuǎn)換)

    這篇文章主要介紹了go 類型轉(zhuǎn)換方式(interface 類型的轉(zhuǎn)換),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • 更高效的GoLevelDB:shardingdb實現(xiàn)分片和并發(fā)讀寫操作

    更高效的GoLevelDB:shardingdb實現(xiàn)分片和并發(fā)讀寫操作

    這篇文章主要介紹了更高效的GoLevelDB:shardingdb實現(xiàn)分片和并發(fā)讀寫操作的相關(guān)資料,需要的朋友可以參考下
    2023-09-09
  • Golang中的信號(Signal)機(jī)制詳解

    Golang中的信號(Signal)機(jī)制詳解

    Signal 是一種操作系統(tǒng)級別的事件通知機(jī)制,進(jìn)程可以響應(yīng)特定的系統(tǒng)信號,這些信號用于指示進(jìn)程執(zhí)行特定的操作,如程序終止、掛起、恢復(fù)等,Golang 的標(biāo)準(zhǔn)庫 os/signal 提供了對信號處理的支持,本文將詳細(xì)講解 Golang 是如何處理和響應(yīng)系統(tǒng)信號的,需要的朋友可以參考下
    2024-01-01
  • Golang中errgroup的常見誤用詳解

    Golang中errgroup的常見誤用詳解

    errgroup和sync.WaitGroup類似,都可以發(fā)起執(zhí)行并等待一組協(xié)程直到所有協(xié)程運(yùn)行結(jié)束,本文主要為大家整理了一些errgroup的常見誤用,有需要的可以參考下
    2024-01-01
  • Golang語言學(xué)習(xí)拿捏Go反射示例教程

    Golang語言學(xué)習(xí)拿捏Go反射示例教程

    這篇文章主要為大家介紹了Golang語言中Go反射示例的教程,教你拿捏Go反射,再也不用被Go反射折磨,有需要的朋友可以共同學(xué)習(xí)參考下
    2021-11-11

最新評論