github.com/leromarinvit/goid@v0.0.0-20170210194639-329af3046b24/goid.go (about) 1 // Package goid returns the current Goroutine ID. 2 package goid 3 4 import ( 5 "reflect" 6 "unsafe" 7 8 "github.com/leromarinvit/typist" 9 ) 10 11 //go:linkname mcall runtime.mcall 12 func mcall(func(uintptr)) 13 14 //go:linkname gogo runtime.gogo 15 func gogo(uintptr) 16 17 var offsetGoid uintptr 18 var offsetSched uintptr 19 20 func init() { 21 pg, err := typist.TypeByString("*runtime.g") 22 if err != nil { 23 return 24 } 25 if pg.Kind() != reflect.Ptr { 26 return 27 } 28 g := pg.Elem() 29 if g.Kind() != reflect.Struct { 30 return 31 } 32 goid, ok := g.FieldByName("goid") 33 if !ok { 34 return 35 } 36 sched, ok := g.FieldByName("sched") 37 if !ok { 38 return 39 } 40 offsetGoid = goid.Offset 41 offsetSched = sched.Offset 42 } 43 44 /* 45 Goid returns the current Goroutine ID. 46 47 It relies on the Go runtime's internals, so it's your own damn fault if it eats 48 your dog. You have been warned. 49 50 BUGS: Occasionally eats your dog 51 */ 52 func Goid() (goid int64) { 53 if offsetGoid == offsetSched { 54 return -1 55 } 56 mcall(func(g uintptr) { 57 id := unsafe.Pointer(g + offsetGoid) 58 goid = *(*int64)(id) 59 sched := g + offsetSched 60 gogo(sched) 61 }) 62 return goid 63 }