github.com/smallnest/goroutine@v1.1.1/gid_go121_test.go (about) 1 // Copyright ©2023 Dan Kortschak. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.21 6 // +build go1.21 7 8 package goroutine 9 10 import ( 11 "fmt" 12 "runtime" 13 "strconv" 14 "strings" 15 "sync" 16 "testing" 17 ) 18 19 func TestParentID(t *testing.T) { 20 var wg sync.WaitGroup 21 for i := 0; i < 1000000; i++ { 22 i := i 23 wg.Add(2) 24 go func() { 25 defer wg.Done() 26 parentID := ID() 27 go func() { 28 defer wg.Done() 29 got := ParentID() 30 want := parentGoid() 31 if got != want { 32 t.Errorf("unexpected parent id for goroutine number %d: mismatch with stack trace: got:%d want:%d", i, got, want) 33 } 34 if got != parentID { 35 t.Errorf("unexpected parent id for goroutine number %d: mismatch with parent: got:%d want:%d", i, got, want) 36 } 37 }() 38 }() 39 } 40 wg.Wait() 41 } 42 43 // parentGoid returns the parent goroutine ID extracted from a stack trace. 44 func parentGoid() int64 { 45 var buf [1 << 10]byte 46 n := runtime.Stack(buf[:], false) 47 _, after, ok := strings.Cut(string(buf[:n]), " in goroutine ") 48 if !ok { 49 panic("cannot get parent goroutine id: no mark") 50 } 51 idField := strings.Fields(after)[0] 52 id, err := strconv.ParseInt(idField, 10, 64) 53 if err != nil { 54 panic(fmt.Sprintf("cannot get parent goroutine id: %v", err)) 55 } 56 return id 57 }