如何获取go协程的ID?

协程G 底层实现

go 复制代码
type g struct {
	// Stack parameters.
	stack       stack   // offset known to runtime/cgo
	stackguard0 uintptr // offset known to liblink
	stackguard1 uintptr // offset known to liblink

	_panic    *_panic // innermost panic - offset known to liblink
	_defer    *_defer // innermost defer
	m         *m      // current m; offset known to arm liblink
	sched     gobuf
	syscallsp uintptr // if status==Gsyscall, syscallsp = sched.sp to use during gc
	syscallpc uintptr // if status==Gsyscall, syscallpc = sched.pc to use during gc
	syscallbp uintptr // if status==Gsyscall, syscallbp = sched.bp to use in fpTraceback
	stktopsp  uintptr // expected sp at top of stack, to check in traceback
	param        unsafe.Pointer
	atomicstatus atomic.Uint32
	stackLock    uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
	goid         uint64
   // ... 其他参数

获取go协程的ID

  1. 获取当前运行的G getg()
go 复制代码
// getg returns the pointer to the current g.
// The compiler rewrites calls to this function into instructions
// that fetch the g directly (from TLS or from the dedicated register).
func getg() *g
  1. 根据goid字段的偏移量 得到ID
go 复制代码
goidOffset := xxxx
// GoID returns the goroutine id of current goroutine
func GoID() int64 {
	g := getg()
	p_goid := (*int64)(unsafe.Pointer(g + goidOffset))
	return *p_goid
}

//go:linkname getg runtime.getg
func getg() uintptr

不同版本的go实现 goid字段的偏移可能不同 可以使用开源库获取 runtime路径下g结构体 然后获取goid的偏移量

go 复制代码
// github.com/modern-go/reflect2/type_map.go

// offset for go1.4
var goidOffset uintptr = 128

func init() {
        // TypeByName return the type by its name, just like Class.forName in java
	gType := reflect2.TypeByName("runtime.g").(reflect2.StructType)
	if gType == nil {
		panic("failed to get runtime.g type")
	}
	goidField := gType.FieldByName("goid")
	goidOffset = goidField.Offset()
}

获取go协程的ID有啥用?

可以实现 Goroutine-Local-Storage cloudwego/localsession实现

相关推荐
JaneConan2 分钟前
鸿蒙报错速查:arkts-no-any any 类型禁用,用了就炸,根因 + 真解法
后端·harmonyos
不简说3 分钟前
JS 代码技巧 vol.8 — 20 个函数式编程实战,把 if/else 拍扁的骚操作
前端·javascript·面试
颜酱32 分钟前
# 02 | 搭骨架:用 LangGraph 编排 12 步工作流(思路)
前端·人工智能·后端
颜酱33 分钟前
02 | 搭骨架:用 LangGraph 编排 12 步工作流
前端·人工智能·后端
嘉伟桑2 小时前
Python调用电价API返回JSON示例:分时电价、现货电价和字段解析
后端
武子康2 小时前
Shippy:确定性工具、会话级 Sandbox 与 Live-Data Eval(4 类收敛 + 7 步实现方案 + 6 类评测指标)
前端·人工智能·后端
我叫黑大帅2 小时前
我为什么单一消费者的场景下,要用 Redis List 当消息队列?
redis·后端·面试
吃饱了得干活2 小时前
亿级订单表分库分表设计,从0到1全流程
java·数据库·面试
AskHarries3 小时前
文件上传系统
后端
止语Lab3 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端