如何得到goroutine 的 id?

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

使用Java的時候很容易得到線程的名字, 比如"Thread.currentThread().getName",這樣就可以進行一些監控操作或者設定線程相關的一些資料。當轉向Golang開發的時候,卻發現Go語言並沒有提供擷取當前goroutine id的操作。這是Golang的開發人員故意為之,避免開發人員濫用goroutine id實現goroutine local storage (類似java的"thread-local" storage), 因為goroutine local storage很難進行記憶體回收。因此儘管以前暴露出了相應的方法,現在已經把它隱藏了。

Please don't use goroutine local storage. It's highly discouraged. In fact, IIRC, we used to expose Goid, but it is hidden since we don't want people to do this.

Potential problems include:

  1. when goroutine goes away, its goroutine local storage won't be GCed. (you can get goid for the current goroutine, but you can't get a list of all running goroutines)
  2. what if handler spawns goroutine itself? the new goroutine suddenly loses access to your goroutine local storage. You can guarantee that your own code won't spawn other goroutines,
    but in general you can't make sure the standard library or any 3rd party code won't do that.

thread local storage is invented to help reuse bad/legacy code that assumes global state, Go doesn't have legacy code like that, and you really should design your code so that state is passed explicitly and not as global (e.g. resort to goroutine local storage)

當然Go的這種隱藏的做法還是有爭議的,有點因噎廢食。在debug log的時候goroutine id是很好的一個監控資訊。本文介紹了兩種擷取goroutine id的方法。

可以用純Go語言擷取當前的goroutine id。代碼如下所示:

12345678910111213141516171819202122232425262728293031323334
package mainimport ("fmt""runtime""strconv""strings""sync")func GoID() int {var buf [64]byten := runtime.Stack(buf[:], false)idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]id, err := strconv.Atoi(idField)if err != nil {panic(fmt.Sprintf("cannot get goroutine id: %v", err))}return id}func main() {fmt.Println("main", GoID())var wg sync.WaitGroupfor i := 0; i < 10; i++ {i := iwg.Add(1)go func() {defer wg.Done()fmt.Println(i, GoID())}()}wg.Wait()}

go run main.go輸出:

1234567891011
main 19 140 51 62 75 106 113 87 124 98 13

它利用runtime.Stack的堆棧資訊。runtime.Stack(buf []byte, all bool) int會將當前的堆棧資訊寫入到一個slice中,堆棧的第一行為goroutine #### […,其中####就是當前的gororutine id,通過這個花招就實現GoID方法了。

但是需要注意的是,擷取堆棧資訊會影響效能,所以建議你在debug的時候才用它。

參考資料

  1. https://groups.google.com/forum/#!topic/golang-nuts/Nt0hVV_nqHE
  2. http://wendal.net/2013/0205.html
  3. http://blog.sgmansfield.com/2015/12/goroutine-ids/
  4. http://dave.cheney.net/2013/09/07/how-to-include-c-code-in-your-go-package
  5. http://golanghome.com/post/566
  6. https://github.com/t-yuki/goid
  7. https://github.com/petermattis/goid.git
  8. https://github.com/huandu/goroutine

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.