Go语言中获取协程ID
简介
java同事都知道,线程会有对应的id,那么go语言中协程有id吗,其实是有的,但是不建议使用。
实在需要使用的话可以使用本文的例子获取
stack
我们先看一下runtime.Stack打印出来的栈结构,其中就包括了协程id
func main() {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
fmt.Println(string(b))
}
goroutine 1 [running]:
main.main()
/Users/shura/GolandProject
通过上面可以看出 1 就是需要的协程id
获取协程id
根据以上的结构,我们就可以截取到协程id
func main() {
fmt.Println(GoID())
}
func GoID() 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
}
输出 1
优化
上面方式虽然确实可以获取到协程id,但是每次都需要做一系列的操作,理论上标准库应该直接提供获取id的方法,但是没提供,那我们自己能不能从源码层面提供呢
我们跟踪runtime.Stack方法进入源码可以看到协程的信息是由 gp := getg()获取到的
再进入getg()查看是一个g的结构体
type g struct {
goid int64
}
这里面就有一个关键的属性goid,但是由于是私有的我们获取不到,所以我们只能从源码层面去添加获取协程id的方法
找到该go文件的路径,例如/Users/shura/support/go/go/src/runtime,执行如下脚本
cat > /Users/shura/support/go/go/src/runtime/shura_goid.go << EOF
package runtime
func GoID() int64{
return getg().goid
}
EOF
测试
func main() {
fmt.Println(runtime.GoID())
fmt.Println(GoID())
}
输出
1
1
欢迎关注,学习不迷路!