go 初始化组件最佳实践

Go 语言初始化最佳实践

在 Go 语言中, 有一个 init() 函数可以对程序进行包级别的初始化, 但 init() 函数有诸多不便, 例如: 无法返回错误, 进行耗时初始化时, 会增加程序启动时间。因此 init() 函数并不适用于所有初始化。

1.初始化方式

在程序进行初始化时,我们应该分析初始化的对象是为: 急切初始化(如: 日志组件, 配置文件读取) 还是 延迟初始化 (如: 数据库连接, 消息队列连接) 。急切初始化大多情况不需要对外部进行连接,且被其他组件所依赖,这时使用 init() 函数进行初始化。延迟初始化对象为需要程序对外部进行连接,且耗时较长, 这时调用 sync.once 进行初始化保证并发安全。

特性延迟初始化使用 init 函数 进行 急切初始化
执行时机首次调用时执行 (懒加载)包被导入时自动执行,在 main 函数之前 (急加载)
并发安全调用 ,专为并发环境设计包初始化由运行时控制,但后续对全局变量的并发访问需额外同步
错误处理可通过封装返回 error (需自行实现)困难,通常只能 log.Fatalpanic
资源消耗按需分配,避免不必要的启动开销程序启动即分配,可能增加启动时间和内存占用
典型应用场景数据库连接池外部服务客户端重型单例对象配置预加载(轻量)、驱动注册(如数据库驱动)、日志系统初始化
可控性高,可灵活控制初始化时机和条件低,由 Go 运行时控制执行顺序和时机

2.单例模式

单例模式是一种创建型设计模式,它的核心目标是确保一个结构体只有一个实例,并提供一个全局访问点来获取这个实例。这种模式在需要控制资源访问或确保全局唯一性的场景中非常有用。

单例模式的关键在于三点:

  1. 唯一实例:单例结构体必须保证只创建一个对象实例。
  2. 自我创建:单例结构体需要自行创建这个实例。
  3. 全局访问:单例结构体必须提供一个允许全局访问该实例的方法。

实现上,通常不允许外部修改结构体,然后提供一个公共方法(如 getInstance())来返回该类的唯一实例。

实现方式描述优点缺点并发安全
饿汉式类加载时就初始化实例。实现简单,线程安全未使用实例时也会创建,可能浪费内存
懒汉式第一次调用时才创建实例。延迟加载,节省资源需加锁保证保证安全,性能有开销

init() 就是饿汉式, 懒汉式 使用 sync.once , 且 sync.once 内部的优化保证了性能和并发安全。

3.代码示例

饿汉式示例:

package confimport ("fmt""github.com/joho/godotenv""github.com/spf13/viper""log""time"
)type Config struct {App      AppConfig
}var _conf = &Config{}func init() {var v = viper.New()v.SetConfigName("StarMall")v.SetConfigType("toml")v.AddConfigPath("E:/starmall/")v.AutomaticEnv()// 读取配置文件err := v.ReadInConfig()if err != nil {fmt.Println(err)log.Printf("config load Error: %v \n", err)} else {log.Println("configuration file was read successfully")}// 将 viper 读到的数据序列化写入 configif err := v.Unmarshal(&_conf); err != nil {now := time.Now()log.Printf("%v: viper Unmarshal err:%s \n", now.Format("2006-01-02 15:04:05"), err)}
}func GetConfig() *Config {return _conf
}

懒汉式 示例:

package databaseimport ("fmt"_ "github.com/go-sql-driver/mysql""github.com/jmoiron/sqlx""github.com/star-find-cloud/star-mall/conf"log "github.com/star-find-cloud/star-mall/pkg/logger""sync"
)type MySQL struct {Conn *sqlx.DB
}var (_mysql = &MySQL{}once   sync.Once
)func initMysql() (*sqlx.DB, error) {var (_db *sqlx.DBerr error)once.Do(func() {c := conf.GetConfig()user := c.Database.MySQL.Userpasswd := c.Database.MySQL.PasswordHost := c.Database.MySQL.MasterHostPort := c.Database.MySQL.MasterPorttimeout := c.Database.MySQL.TimeoutDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/?charset=utf8mb4&parseTime=True&timeout=%ss", user, passwd, Host, Port, timeout)_db, err = sqlx.Connect("mysql", DSN)if err != nil {fmt.Println("Database error, please check the logs.")//fmt.Println(c.Database.MySQL)log.MySQLLogger.Errorf("MySQL master connect faild: %s \n", err)} else {log.MySQLLogger.Infof("MySQL master connection successful: %s\n", Host)}_db.SetMaxOpenConns(c.Database.MySQL.MaxOpenConns)_db.SetMaxIdleConns(c.Database.MySQL.MaxIdleConns)})return _db, err
}func NewMySQL() (*MySQL, error) {db, err := initMysql()_mysql.Conn = dbreturn _mysql, err
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/921247.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/921247.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

域名暂停解析是怎么回事

域名注册和使用是需要付费的,如果没有及时续费,域名注册商就会暂停该域名的解析服务。相关数据显示,大约有 30% 的域名暂停解析情况是由于欠费引起的。比如,有个小公司的网站域名到期了,负责续费的员工忘记操作&#x…

前端开发的“三剑客”—— ​​HTML、CSS、JavaScript​​

前端开发的“三剑客”—— ​​HTML、CSS、JavaScript​​,是构建所有网页和Web应用的基石。它们分工明确又紧密协作,共同实现了网页的“内容结构”“视觉表现”和“交互行为”。以下是三者的详细解析及协作逻辑:​​1. HTML:网页…

TDengine TIMEDIFF() 函数用户使用手册

TDengine TIMEDIFF() 函数详细使用手册 目录 功能概述函数语法参数说明返回值说明版本变更说明技术特性使用场景及示例时间单位处理数据类型兼容性注意事项常见问题最佳实践 功能概述 TIMEDIFF() 函数用于计算两个时间戳的差值,返回 expr1 - expr2 的结果。结果…

数据结构:栈和队列(上)

汇总代码见:登录 - Gitee.com 上一篇文章:数据结构:双向链表-CSDN博客 与本文相关的结构体传参:自定义类型:结构体-CSDN博客 1.栈 1.1概念和结构 栈:一种特殊的线性表,其只允许在固定的一端…

文档抽取技术:提取非结构化文档中的关键信息,提升档案管理、金融保险和法律合规领域的效率与准确性

在信息爆炸的时代,各种机构、企业等都面临着海量非结构化文档数据的挑战。报告、合同、票据、档案记录、法律文书等文档中蕴藏着巨大的数据,但传统依靠人工阅读、理解和录入的方式效率低下、成本高昂且容易出错。文档抽取技术作为人工智能和自然语言处理…

雷柏VT1 MAX评测:原生中小手形电竞鼠标 但既不仅限于中小手形 也不仅限于电竞

一、前言:真正针对中小手形设计的电竞鼠标 雷柏第二代VT系列电竞鼠标我们已经体验过很多款了,基本都是针对大中手形设计的外形模具,只有VT3s系列是VT3系列的缩小版,更适合中小手形使用,但也只是对中大手形模具重新优化…

新客户 | TDengine 时序数据库赋能开源鸿蒙物联展区实时监控与展示

在工业物联网快速发展的当下,企业普遍面临着两大挑战:一是设备种类繁多、接入标准不一,导致系统建设容易陷入“数据孤岛”;二是实时监控和多场景联动的需求越来越强烈,但传统数据库在高频写入与多维分析上难以兼顾&…

深入剖析 ConcurrentHashMap:Java 并发编程的基石

目录 【1】Java 7 中 ConcurrentHashMap 的实现原理 1.分段锁(Segment) 2. 数据结构 3. 操作流程 【2】Java 8 中 ConcurrentHashMap 的改进 1.红黑树的引入 2.CAS 操作 3.数据结构的变化 【3】ConcurrentHashMap 的常用方法及使用示例 1.put(…

【会员专享数据】2020-2022年我国乡镇的逐日地表气压数据(Shp/Excel格式)

之前我们分享过2020—2022年中国0.01分辨率逐日地表气压栅格数据(可查看之前的文章获悉详情)!该数据是研究者张凌, 胡英屹等发布在国家冰川冻土沙漠科学数据中心平台上的高分辨地表气压数据。很多小伙伴拿到数据后反馈栅格数据不太方便使用&a…

第二阶段WinForm-12:UI控件库

1_验证码与条形码 1.1_条码基础知识 条码:条码是由一组按一定编码规则排列的条、空符号组成,用以表示一定的字符、数字及符号组成的信息 1.2_一维码 (1)Code 128 Code 128 是一种密度很高的字母数字代码系统,可对其…

别再误会了!Redis 6.0 的多线程,和你想象的完全不一样

技术解析核心误区:Redis 6.0是完全多线程的吗?No. Redis 6.0引入的多线程,只用于网络I/O的读写和数据的解析。而核心的命令执行(比如 GET, SET, HGETALL 等)依然是单线程的。Redis的架构演进,就像是把一个复…

23种设计模式——抽象工厂模式(Abstract Factory Pattern)详解

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。 🍎个人主页:Meteors.的博客 💞当前专栏:设计模式 ✨特色专栏:知识分享 &#x…

本地部署开源数据生成器项目实战指南

本地部署开源数据生成器项目实战指南 前言 在当今大数据和人工智能时代,高质量数据集对于模型训练和算法开发至关重要。然而,获取真实且合规的数据集往往面临隐私、成本和法律等多重挑战。合成数据生成技术为此提供了优雅的解决方案,它能够…

2025React面试题集锦

1. React 是什么?它有哪些主要特点? React 是由Facebook开发的开源JavaScript库,用于构建用户界面(UI),尤其适合开发复杂的单页应用(SPA)。 主要特点: 声明式编程:只需描述UI应该是什么样子(如return <div>Hello</div>),React会自动处理DOM更新,无需…

设计模式:迭代器模式(Iterator Pattern)

文章目录一、概念二、实例分析三、示例代码一、概念 迭代器模式 是一种 行为型设计模式&#xff0c;用于在不暴露集合对象内部结构的前提下&#xff0c;顺序访问集合中的元素。 换句话说&#xff1a; 集合类只负责数据存储&#xff1b;迭代器类负责遍历集合&#xff1b;使用者…

Vue 3 学习路线指南

阶段一:基础入门 (1-2周) 1.1 环境准备 # 安装 Node.js (推荐 18+ 版本) # 安装 Vue CLI 或使用 Vite npm create vue@latest my-vue-app cd my-vue-app npm install npm run dev1.2 Vue 3 核心概念 响应式系统:ref(), reactive(), computed() 组合式 API:setup() 函数 模…

使用 `hover:not-[:has(:hover)]` 避免「父元素和子元素同时 hover」时的样式冲突

:hover:not-(:has(:hover)) has() CSS 4 引入的“父选择器”&#xff0c;意思是&#xff1a;匹配那些里面包含某个子元素/状态的元素。 例如&#xff1a;:has(:hover) 表示「自身包含正在被 hover 的子元素」。 :not() 取反伪类&#xff0c;表示不匹配里面的条件。 比如我…

第三十天-DMA串口实验

一、DMA概述二、DMA通道注意&#xff0c;想要往串口中写数据&#xff0c;外部请求信号应该是USARTx_TX&#xff0c;当DR寄存器为空时&#xff0c;产生TX信号&#xff0c;请求DMA。反之&#xff0c;从串口中读数据&#xff0c;外部请求信号应该是USARTx_RX&#xff0c;当DR寄存器…

C/C++ 中的inline(内联函数关键字)详解

在 C/C 编程中&#xff0c;函数调用虽然带来了代码复用和可读性提升&#xff0c;但频繁调用小型函数可能会产生额外的调用开销&#xff08;call overhead&#xff09;&#xff0c;比如栈帧的建立与销毁、参数传递等。 为了减少这种开销&#xff0c;C 引入了 inline&#xff08;…

2025 年高教社杯全国大学生数学建模竞赛A 题 烟幕干扰弹的投放策略完整成品 思路 模型 代码 结果 全网首发高质量!!!

烟幕干扰弹主要通过化学燃烧或爆炸分散形成烟幕或气溶胶云团,在目标前方特定空域形成遮蔽&#xff0c;干扰敌方导弹&#xff0c;具有成本低、效费比高等优点。随着烟幕干扰技术的不断发展&#xff0c;现已有多种投放方式完成烟幕干扰弹的定点精确抛撒,即在抛撒前能精确控制烟幕…