最新公告
  • 欢迎您光临码农资源网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!加入我们
  • 带有 Go 泛型的单例模式

    带有 go 泛型的单例模式

    问题内容

    我正在尝试找出在 golang 中为泛型变量实现单例的最不糟糕的方法。使用普通的 sync.once 模式与全局变量是行不通的,因为通用类型信息在那里不可用(如下)。

    这个示例是人为设计的,但实际上,维护单例的代码可以与定义 t 的客户端代码分开(例如在库中)。

    假设此库代码,其中 t 的具体值未知:

    type cache[t any] struct{}
    
    var (
        cacheonce sync.once
        cache     cache[any] // global singleton
    )
    
    func getorcreatecache[t any]() cache[t] {
        cacheonce.do(func() {
            typedcache := buildcache()
            cache = typedcache.(cache[any]) // invalid type assertion
        })
        return cache.(cache[t]) // invalid type assertion
    }

    并假设这个单独的客户端代码,其中 t 被定义为 string

    stringCache := getOrCreateCache[string]()

    实现这一目标的最佳方法是什么?

    正确答案

    我最终使用 atomic.pointer api 解决了这个问题,并将其整合到一个简单的库中,供其他感兴趣的人使用:单线。使用单线态重新处理原始帖子如下所示:

    示例库代码:

    type cache[t any] struct{}
    
    var singleton = &singlet.singleton{}
    
    func getorcreatecache[t any]() (cache[t], err) {
        return singlet.getordo(singleton, func() cache[t] {
            return cache[t]{}
        })
    }

    客户端代码:

    stringcache := getorcreatecache[string]()

    以及支持此功能的 singlet 库代码:

    var ErrTypeMismatch = errors.New("the requested type does not match the singleton type")
    
    type Singleton struct {
        p   atomic.Pointer[any]
        mtx sync.Mutex
    }
    
    func GetOrDo[T any](singleton *Singleton, fn func() T) (result T, err error) {
        maybeResult := singleton.p.Load()
        if maybeResult == nil {
            // Lock to guard against applying fn twice
            singleton.mtx.Lock()
            defer singleton.mtx.Unlock()
            maybeResult = singleton.p.Load()
    
            // Double check
            if maybeResult == nil {
                result = fn()
                var resultAny any = result
                singleton.p.Store(&resultAny)
                return result, nil
            }
        }
    
        var ok bool
        result, ok = (*maybeResult).(T)
        if !ok {
            return *new(T), ErrTypeMismatch
        }
        return result, nil
    }

    我希望对遇到这种情况的其他人有所帮助。

    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!
    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
    如有侵权请发送邮件至1943759704@qq.com删除

    码农资源网 » 带有 Go 泛型的单例模式
    • 7会员总数(位)
    • 25846资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 293稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情