協程ID作用
類似於其他語言的線程ID,C++當中,每個請求過來,開啓一個單獨的線程處理它,那麼線程的ID是當前請求的唯一標識符。有了唯一標識符以後,就可以創建一個線程安全的全局map來管理每個請求的生命週期的變量。
在go語言中,谷歌開發者不建議大家獲取協程ID,主要是爲了GC更好的工作,濫用協程ID會導致GC不能及時回收內存。如果一個第三方庫使用了協程ID,那麼使用該庫的人將會莫名中招。
下面是協程ID最常規的使用方式
package gomap
import (
"bytes"
"fmt"
"runtime"
"strconv"
"sync"
)
var goGlobalMap sync.Map
func Set(k, v interface{}) {
goGlobalMap.Store(fmt.Sprintf("%d_%v", goID(), k), v)
}
func Get(k interface{}) interface{} {
if v, ok := goGlobalMap.Load(fmt.Sprintf("%d_%v", goID(), k)); ok {
return v
}
return nil
}
func Del(k interface{}) {
goGlobalMap.Delete(fmt.Sprintf("%d_%v", goID(), k))
}
func goID() 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
}