Golang - 獲取協程ID,從此走上一條曲折的不歸路

協程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
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章