✖️

puzpuzpuz/xsync パッケージの紹介

2024/10/29に公開

こんばんは。ふろーです。

題名通り。

puzpuzpuz/xsync

https://github.com/puzpuzpuz/xsync

Go 1.18で導入されたGenericsを使用したgoroutine-safeなMapライブラリです。
従来までは、goroutineによる並列実行に対応したMapを作成する場合は、手動でsync.Mutex を利用してロックを掛けたり、sync.Map を使って型変換を実施する必要がありました。
xsyncを使うと、ロックの取得や型の処理をライブラリが管理するため、並列処理に頭を悩ませることが少なくなります。

これまで

sync.Mutex の場合


type SimpleMap struct {
    mutex *sync.Mutex
    m map[string]any
}

func NewSimpleMap(){
    return &SimpleMap{
        mutex: &sync.Mutex{},
        m: map[string]any{},
    }
}

func (sm *SimpleMap) Store(key string, value any) {
    // ❌① ロックの取得を管理する必要がある...
    sm.mutex.Lock()
    defer sm.mutex.Unlock()
    sm.m[key] = value
}

// ❌② 戻り値がany型になっている...
func (sm *SimpleMap) Load(key string) any {
    sm.mutex.Lock()
    defer sm.mutex.Unlock()
    return sm.m[key]
}

sync.Map の場合


type SimpleMap struct {
    m *sync.Map
}

func NewSimpleMap(){
    return &SimpleMap{
        m: &sync.Map{},
    }
}

func (sm *SimpleMap) Store(key string, value any) {
    // ✅① ロックの取得管理をする必要がない!
    m.Store(key, value)
}

// ❌② 戻り値はany型のまま...
func (sm *SimpleMap) Load(key string) any {
    value := sm.m[key]
    // ❓② 型アサーションをすれば型は一応付けれる
    // v := sm.m.Load().(any)
    return value
}

puzpuzpuz/xsync の場合

xsync.MapOf[K,V] の場合を使うと...

type SimpleMap struct {
    // ✅① ロックの取得管理はもちろんやってくれる!
    m *xsync.MapOf[string, string] // ✅② Genericsを使うことによってKey,Valueの両方に型を付けれる
}

func NewSimpleMap(){
    return &SimpleMap{
        m: xsync.NewMapOf[string, string](), // NewMapOf() 関数で初期化が可能
    }
}

func (sm *SimpleMap) Store(key string, value string) {
    m.Store(key, value)
}

// ✅② 戻り値に型がついている!
func (sm *SimpleMap) Load(key string) string {
   return sm.m.Load()
}

短いですが紹介としては以上です。
個人的には便利なので頻繁に使っていますが、他にもxsync.Counter など、atomicなカウンターなどが用意されているようです。

Discussion