You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言包内线程安全Singleton实现及私有实例初始化问询

Go包内线程安全Singleton的实现方案

要在sess包内实现线程安全的单例,确保多次导入包只会存在一个实例,无需在main中初始化后传递,可以采用Go标准库的sync.Once来实现,这是Go生态中推荐的线程安全单例方案。

修改后的sess包代码

package sess

import (
    "sync"
)

type pool struct {
    lock     sync.RWMutex
    sessions map[string]*session
}

// 包级私有变量:单例实例和初始化控制对象
var (
    instance *pool
    once     sync.Once
)

// GetInstance 获取全局唯一的pool实例,线程安全
func GetInstance() *pool {
    // sync.Once.Do确保内部函数仅执行一次
    once.Do(func() {
        instance = &pool{
            sessions: map[string]*session{},
        }
    })
    return instance
}

func (p *pool) Set(sid string, s *session) {
    p.lock.Lock()
    defer p.lock.Unlock()
    p.sessions[sid] = s
}

func (p *pool) Get(sid string) (*session, bool) {
    p.lock.RLock()
    defer p.lock.RUnlock()
    s, ok := p.sessions[sid]
    return s, ok
}

核心原理说明

  • sync.Once是Go专门用于保证代码仅执行一次的同步原语,无论多少goroutine同时调用GetInstance,once.Do内的初始化逻辑只会执行一次,完全避免了并发初始化的竞态问题。
  • instance是包级私有变量(小写开头),外部无法直接访问或修改,只能通过GetInstance方法获取,确保实例的全局唯一性。

使用方式

在任何导入sess包的文件中,直接调用GetInstance即可获取同一个实例,无需在main中初始化后传递:

package main

import "your/path/to/sess"

func main() {
    sessions := sess.GetInstance()
    // 直接调用sessions.Set()/Get()方法即可
}

补充说明

如果需要饿加载(包被导入时就完成初始化),可以直接在包级别初始化实例,但懒加载(第一次调用时初始化)更灵活,能避免不必要的资源占用:

// 饿加载方式,直接在包级别初始化
var instance = &pool{
    sessions: map[string]*session{},
}

func GetInstance() *pool {
    return instance
}

这种方式同样线程安全,因为Go的包初始化是单线程执行的,不会出现并发问题。

内容的提问来源于stack exchange,提问作者clarkk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:00:23