github.com/rolandhe/saber@v0.0.4/utils/idutils.go (about) 1 // Package utils, daog包使用的工具,现在只包含读取当前goroutine id的工具,未来可能会扩展 2 package utils 3 4 import ( 5 "bytes" 6 "errors" 7 "fmt" 8 "runtime" 9 "strconv" 10 ) 11 12 var goroutineSpace = []byte("goroutine ") 13 14 // GetGoRoutineId 获得当前goroutine id函数 15 func GetGoRoutineId() (uint64, error) { 16 b := make([]byte, 64) 17 b = b[:runtime.Stack(b, false)] 18 // Parse the 4707 out of "goroutine 4707 [" 19 b = bytes.TrimPrefix(b, goroutineSpace) 20 i := bytes.IndexByte(b, ' ') 21 if i < 0 { 22 panic(fmt.Sprintf("No space found in %q", b)) 23 } 24 b = b[:i] 25 n, err := parseUintBytes(b, 10, 64) 26 if err != nil { 27 return 0, err 28 } 29 return n, nil 30 } 31 32 func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) { 33 var cutoff, maxVal uint64 34 35 if bitSize == 0 { 36 bitSize = strconv.IntSize 37 } 38 39 s0 := s 40 switch { 41 case len(s) < 1: 42 err = strconv.ErrSyntax 43 goto Error 44 45 case 2 <= base && base <= 36: 46 // valid base; nothing to do 47 48 case base == 0: 49 // Look for octal, hex prefix. 50 switch { 51 case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'): 52 base = 16 53 s = s[2:] 54 if len(s) < 1 { 55 err = strconv.ErrSyntax 56 goto Error 57 } 58 case s[0] == '0': 59 base = 8 60 default: 61 base = 10 62 } 63 64 default: 65 err = errors.New("invalid base " + strconv.Itoa(base)) 66 goto Error 67 } 68 69 n = 0 70 cutoff = cutoff64(base) 71 maxVal = 1<<uint(bitSize) - 1 72 73 for i := 0; i < len(s); i++ { 74 var v byte 75 d := s[i] 76 switch { 77 case '0' <= d && d <= '9': 78 v = d - '0' 79 case 'a' <= d && d <= 'z': 80 v = d - 'a' + 10 81 case 'A' <= d && d <= 'Z': 82 v = d - 'A' + 10 83 default: 84 n = 0 85 err = strconv.ErrSyntax 86 goto Error 87 } 88 if int(v) >= base { 89 n = 0 90 err = strconv.ErrSyntax 91 goto Error 92 } 93 94 if n >= cutoff { 95 // n*base overflows 96 n = 1<<64 - 1 97 err = strconv.ErrRange 98 goto Error 99 } 100 n *= uint64(base) 101 102 n1 := n + uint64(v) 103 if n1 < n || n1 > maxVal { 104 // n+v overflows 105 n = 1<<64 - 1 106 err = strconv.ErrRange 107 goto Error 108 } 109 n = n1 110 } 111 112 return n, nil 113 114 Error: 115 return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} 116 } 117 118 // Return the first number n such that n*base >= 1<<64. 119 func cutoff64(base int) uint64 { 120 if base < 2 { 121 return 0 122 } 123 return (1<<64-1)/uint64(base) + 1 124 }