golang 日誌打印 如何添加 goroutinei

在 Go 語言中,標準庫沒有直接提供獲取 goroutine ID 的功能,因此,如果我們想在日誌中添加 goroutine ID,需要藉助一些非標準的方式來實現。

方法 1: 通過第三方庫(如 github.com/petermattis/goid

github.com/petermattis/goid 是一個常用的第三方庫,它可以幫助我們獲取當前 goroutine 的 ID。我們可以通過它來實現帶有 goroutine ID 的日誌。

安裝 goid

go get github.com/petermattis/goid

使用示例

package main

import (
    "fmt"
    "log"
    "os"
    "github.com/petermattis/goid"
)

func main() {
    // 設置日誌輸出格式
    log.SetFlags(0) // 禁用時間戳,保持輸出簡單
    log.SetOutput(os.Stdout)

    // 在不同的 goroutine 中打印日誌
    go func() {
        log.Printf("goroutine[%d]: Hello from goroutine 1", goid.Get())
    }()

    go func() {
        log.Printf("goroutine[%d]: Hello from goroutine 2", goid.Get())
    }()

    // 主 goroutine
    log.Printf("goroutine[%d]: Hello from main goroutine", goid.Get())

    // 防止程序過快退出
    select {}
}

輸出示例

goroutine[1]: Hello from main goroutine
goroutine[6]: Hello from goroutine 1
goroutine[7]: Hello from goroutine 2

在這個例子中,每條日誌都包含了當前 goroutine 的 ID。

方法 2: 自行封裝日誌函數

如果不想依賴第三方庫,也可以自行實現類似功能。雖然 Go 標準庫沒有提供直接獲取 goroutine ID 的方法,但我們可以通過解析運行時調用棧的方式來間接獲取 goroutine ID。

代碼實現

package main

import (
    "bytes"
    "fmt"
    "log"
    "os"
    "runtime"
    "strconv"
)

func getGoroutineID() uint64 {
    b := make([]byte, 64)
    b = b[:runtime.Stack(b, false)]
    b = bytes.TrimPrefix(b, []byte("goroutine "))
    b = b[:bytes.IndexByte(b, ' ')]
    n, _ := strconv.ParseUint(string(b), 10, 64)
    return n
}

func logWithGoroutineID(message string) {
    gid := getGoroutineID()
    log.Printf("goroutine[%d]: %s", gid, message)
}

func main() {
    // 設置日誌輸出格式
    log.SetFlags(0) // 禁用時間戳,保持輸出簡單
    log.SetOutput(os.Stdout)

    // 在不同的 goroutine 中打印日誌
    go func() {
        logWithGoroutineID("Hello from goroutine 1")
    }()

    go func() {
        logWithGoroutineID("Hello from goroutine 2")
    }()

    // 主 goroutine
    logWithGoroutineID("Hello from main goroutine")

    // 防止程序過快退出
    select {}
}

輸出示例

goroutine[1]: Hello from main goroutine
goroutine[6]: Hello from goroutine 1
goroutine[7]: Hello from goroutine 2

注意事項

  1. 效率問題: 解析堆棧來獲取 goroutine ID 不是很高效的方法,尤其在高併發的場景下可能會影響性能。

  2. 不保證穩定性: 解析堆棧信息依賴於 Go 內部實現細節,在 Go 版本更新時,堆棧的格式可能會發生變化,從而影響 goroutine ID 的獲取。

  3. 生產環境謹慎使用: 如果要在生產環境中使用,請權衡性能開銷和功能需求。

總結而言,最簡單的方法是使用第三方庫 github.com/petermattis/goid 來獲取 goroutine ID,這也是多數開發者的選擇。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/wlkprse389fjtR3aHurbuw