hit*_*lin 4 concurrency logging runtime go
如何获取 Goroutine 的运行时 ID?
我从导入的包中获取交错日志 - 一种方法是向每个 goroutine 的日志添加唯一标识符。
我找到了一些参考资料runtime.GoID:
func worker() {
id := runtime.GoID()
log.Println("Goroutine ID:", id)
}
Run Code Online (Sandbox Code Playgroud)
但看起来现在已经过时/已被删除 - https://pkg.go.dev/runtime?
Go 故意选择不提供 ID,因为这会鼓励更糟糕的软件并损害整个生态系统:https://go.dev/doc/faq#no_goroutine_id
一般来说,去匿名化 goroutine 的愿望是一个设计缺陷,强烈不建议这样做。几乎总会有更好的方法来解决手头的问题。例如,如果您需要唯一标识符,则应将其传递到函数中或可能通过 context.Context 传递。
然而,运行时内部需要 ID 来实现。出于教育目的,您可以通过以下方式找到它们:
package main
import (
"bytes"
"errors"
"fmt"
"runtime"
"strconv"
)
func main() {
fmt.Println(goid())
done := make(chan struct{})
go func() {
fmt.Println(goid())
done <- struct{}{}
}()
go func() {
fmt.Println(goid())
done <- struct{}{}
}()
<-done
<-done
}
var (
goroutinePrefix = []byte("goroutine ")
errBadStack = errors.New("invalid runtime.Stack output")
)
// This is terrible, slow, and should never be used.
func goid() (int, error) {
buf := make([]byte, 32)
n := runtime.Stack(buf, false)
buf = buf[:n]
// goroutine 1 [running]: ...
buf, ok := bytes.CutPrefix(buf, goroutinePrefix)
if !ok {
return 0, errBadStack
}
i := bytes.IndexByte(buf, ' ')
if i < 0 {
return 0, errBadStack
}
return strconv.Atoi(string(buf[:i]))
}
Run Code Online (Sandbox Code Playgroud)
输出示例:
1 <nil>
19 <nil>
18 <nil>
Run Code Online (Sandbox Code Playgroud)
goid它们也可以通过访问结构中的字段来通过汇编找到(不太可移植)g。这就是像github.com/petermattis/goid这样的包通常的做法。
| 归档时间: |
|
| 查看次数: |
5713 次 |
| 最近记录: |