獲取 Goroutine ID

via: http://blog.sgmansfield.com/2015/12/goroutine-ids/
作者:Scott Mansfield

獲取 Goroutine ID


Goroutine ID 真實存在嗎?

當然存在。
Go 運行時一定有某種方式來跟蹤 goroutine ID。

那我該使用它們嗎?

不該。

有沒有哪些包是我可以使用的?

已有的來自 Go Team 成員的包,被評價爲“用此包者,將入地獄。

也有一些包基於 goroutine id 來建立 goroutine local storage,如:
- github.com/jtolds/gls
- github.com/tylerb/gls
但都有悖於 GO 語言的設計原則。

最簡代碼

如果讀到這裏,你仍“執迷不悟”,那麼下面就將展示如何獲取當前的 goroutine id :

Go 源碼中的駭客(Hacky)代碼

下列代碼源於 Brad Fitzpatrick 的 http/2 庫。它被整合進了 Go 1.6 中,僅僅被用於調試而非常規開發。

package main


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


func main() {
    fmt.Println(getGID())
}


func getGID() 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
}

工作原理解釋

通過解析調試信息來獲取 goroutine id 是可行的. http/2 庫就使用調試性的代碼來對連接進行追蹤查看。但僅僅是將 goroutine id 用於調試而已。

調試信息可以通過調用 runtime.Stack(buf []byte, all bool) int來獲取,它會以文本形式打印堆棧信息到緩衝區中。堆棧信息的第一行會是如下文本: “goroutine #### […”
這裏的 #### 就是真實的 goroutine id. 剩餘代碼不過是進行一些文本操作來提取和解析堆棧信息中的數字。

CGo 版本對應的合法代碼

C 版本的代碼來自 github.com/davecheney/junk/id (譯者注:源鏈接失效,請訪問github.com/davecheney/junk/tree/master/id)。代碼中直接獲取了當前 goroutine 的 goid 屬性並返回它的值。

文件名: id.c

#include "runtime.h"


int64 ·Id(void) {
return g->goid;
}

文件名: id.go

package id


func Id() int64

我該怎麼做?

遠離 goroutine id 吧,並忘記它們的存在。從 GO 語言設計的角度來看,使用它們是危險的。因爲幾乎所有使用的目的都是去做一些和 goroutine-local 相關的事情。
而這違反了 Go 語言編程的“Share Memory By Communicating”原則。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章