获取 Goroutine ID

MaleicAcid · 2018-01-10 01:12:44 · 5018 次点击 · 预计阅读时间 2 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2018-01-10 01:12:44 的文章,其中的信息可能已经有所发展或是发生改变。

Goroutine ID 真实存在吗?

当然存在。

Go 运行时一定有某种方法来跟踪 goroutine ID。

那我该使用它们吗?

不该。

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

已有的来自 Go Team 成员的包,被评价为“用此包者,将入地狱。

也有一些包基于 goroutine id 来建立 goroutine 本地存储,如:

但都有悖于 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。代码中直接获取了当前 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” 原则。


via: http://blog.sgmansfield.com/2015/12/goroutine-ids/

作者:Scott Mansfield  译者:MaleicAcid  校对:polaris1119

本文由 GCTT 原创编译,Go语言中文网 荣誉推出


有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

5018 次点击  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传