Go中单例+工厂模式通过sync.Once实现线程安全单例,接口+工厂函数解耦实现,支持运行时配置与延迟初始化,避免init()硬编码、导出变量等陷阱。
在 Go 语言中,单例 + 工厂模式的组合常用于管理全局、可配置、需统一初始化的核心对象(如数据库连接池、日志实例、配置管理器等)。Go 本身没有类和构造函数,但可通过包级变量 + 惰性初始化 + 接口抽象来优雅实现:单例保证全局唯一,工厂负责按需创建具体类型,同时隐藏初始化细节。
Go 标准库的 sync.Once 是实现单例最推荐的方式——它确保初始化函数仅执行一次,且并发安全,无需手动加锁。
示例:全局日志实例单例
var (
logger *zap.Logger
once sync.Once
)
func GetLogger() *zap.Logger {
once.Do(func() {
l, _ := zap.NewProduction()
logger = l
})
return logger
}
调用 GetLogger() 多次始终返回同一个实例,首次调用时完成初始化。
定义统一接口,让不同环境或配置可返回不同实现(如开发用 console logger,生产用 file logger),再通过工厂函数封装创建逻辑:
type Logger interface {
Info(string, ...zap.Field)
Error(string, ...zap.Field)
}
func NewLogger(env string) Logger {
switch env {
case "dev":
l, _ := zap.NewDevelopment()
return l
case "prod":
l, _ := zap.NewProduction()
return l
default:
return zap.NewNop() // 空实现,避免 panic
}
}
此时单例可基于工厂结果构建:
var (
globalLogger Logger
loggerOnce sync.Once
)
func GetGlobalLogger(env string) Logger {
loggerOnce.Do(func() {
globalLogger = NewLogger(env)
})
return globalLogger
}
实际项目中,配置往往来自命令行、环境变量或配置文件,不能在包初始化阶段硬编码。建议将配置参数传入工厂,并缓存配置+实例绑定关系:
map[string]instance 缓存已创建的实例,键为配置标识(如 "mysql-primary")sync.RWMutex 支持高频读、低频写场景示例简版(无锁优化,适合简单场景):
type DBFactory struct {
instances map[string]*sql.DB
mu sync.RWMutex
}
func (f *DBFactory) GetDB(name string, dsn string) (*sql.DB, error) {
f.mu.RLock()
if db, ok := f.instances[name]; ok {
f.mu.RUnlock()
return db, nil
}
f.mu.RUnlock()
f.mu.Lock()
defer f.mu.Unlock()
if db, ok := f.instances[name]; ok {
return db, nil
}
db, err := sql.Open("mysql", dsn)
if err != nil {
return nil, err
}
f.instances[name] = db
return db, nil
}
Go 中实现单例+工厂易踩的坑:
var Logger *zap.Logger):破坏封装,外部可随意修改,应只暴露获取函数logger.SetLevel()),而非直接赋值Close() 或 Shutdown() 方法,并由主程序统一调用
# mysql
# go
# golang
# 编码
# switch
# 环境变量
# 配置文件
# 无锁
# 标准库
# String
# 封装
# 构造函数
# 全局变量
# 结构体
# 接口
# 线程
# var
# map
# 并发
# console
# 对象
# 数据库
# 首次
# 句柄
# 主程序
# 能在
# 管理器
# 而非
# 可通过
# 并由
# 不等于
# 绑定
相关文章:
建站之星CMS五站合一模板配置与SEO优化指南
c++如何打印函数堆栈信息_c++ backtrace函数与符号名解析【方法】
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
c# 在高并发下使用反射发射(Reflection.Emit)的性能
免费网站制作appp,免费制作app哪个平台好?
如何在阿里云香港服务器快速搭建网站?
专业公司网站制作公司,用什么语言做企业网站比较好?
江苏网站制作公司有哪些,江苏书法考级官方网站?
如何用低价快速搭建高质量网站?
如何在Windows环境下新建FTP站点并设置权限?
如何通过虚拟机搭建网站?详细步骤解析
如何通过免费商城建站系统源码自定义网站主题与功能?
如何处理“XML格式不正确”错误 常见XML well-formed问题解决方法
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
网站规划与制作是什么,电子商务网站系统规划的内容及步骤是什么?
开封网站制作公司,网络用语开封是什么意思?
C#如何在一个XML文件中查找并替换文本内容
北京营销型网站制作公司,可以用python做一个营销推广网站吗?
东莞专业制作网站的公司,东莞大学生网的网址是什么?
网站制作公司排行榜,四大门户网站排名?
零基础网站服务器架设实战:轻量应用与域名解析配置指南
如何通过远程VPS快速搭建个人网站?
建站之星24小时客服电话如何获取?
商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
外汇网站制作流程,如何在工商银行网站上做外汇买卖?
linux top下的 minerd 木马清除方法
小米网站链接制作教程,请问miui新增网页链接调用服务有什么用啊?
建站之星如何助力企业快速打造五合一网站?
如何选择香港主机高效搭建外贸独立站?
小型网站建站如何选择虚拟主机?
利用JavaScript实现拖拽改变元素大小
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
如何快速生成橙子建站落地页链接?
Swift中循环语句中的转移语句 break 和 continue
湖北网站制作公司有哪些,湖北清能集团官网?
建站DNS解析失败?如何正确配置域名服务器?
建站之星免费版是否永久可用?
非常酷的网站设计制作软件,酷培ai教育官方网站?
网站制作需要会哪些技术,建立一个网站要花费多少?
网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?
定制建站价位费用解析与套餐推荐全攻略
制作销售网站教学视频,销售网站有哪些?
韩国服务器如何优化跨境访问实现高效连接?
专业制作网站的公司哪家好,建立一个公司网站的费用.有哪些部分,分别要多少钱?
常州自助建站:操作简便模板丰富,企业个人快速搭建网站
已有域名如何快速搭建专属网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。