当前位置: 首页 > java >正文

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.xdnf.cn/news/20082.html

相关文章:

  • ai生成ppt工具有哪些?10款主流AI生成PPT工具盘点
  • 中州养老:角色管理的角色分页查询
  • 渗透测试与网络安全审计的关系
  • (论文速读)Navigation World Models: 让机器人像人类一样想象和规划导航路径
  • MySQL主从复制之进阶延时同步、GTID复制、半同步复制完整实验流程
  • aippt自动生成工具有哪些?一文看懂,总有一款适合你!
  • Java数据结构——栈(Stack)和队列(Queue)
  • Qt---状态机框架QState
  • 【Sharding-JDBC】​Spring/Spring Boot 集成 Sharding-JDBC,分表策略与 API、YAML 配置实践​
  • 达梦数据库-共享内存池
  • 3.3.3 钢结构工程施工
  • Kubernetes知识点(三)
  • 探究Linux系统的SSL/TLS证书机制
  • 河南萌新联赛2025第(七)场:郑州轻工业大学
  • 直接让前端请求代理到自己的本地服务器,告别CV报文到自己的API工具,解放双手
  • android View详解—自定义ViewGroup,流式布局
  • 亚洲数字能源独角兽的 “安全密码”:Parasoft为星星充电筑牢软件防线
  • MongoDB 高可用部署:Replica Set 搭建与故障转移测试
  • SpringCloud微服务基于nacos注册中心的服务发现模式及OpenFeign的使用
  • Redis在商城开发中起到什么作用?
  • 漏洞修复 Nginx TLSSSL 弱密码套件
  • 2025国赛C题保姆级教程思路分析 NIPT 的时点选择与胎儿的异常判定
  • 【完整源码+数据集+部署教程】陶瓷物品实例分割系统源码和数据集:改进yolo11-LVMB
  • 第22节:性能监控与内存管理——构建高性能3D应用
  • 3ds Max流体模拟终极指南:打造逼真液体效果,从瀑布到杯中溢出的饮料!
  • 240. 搜索二维矩阵 II
  • 2025年含金量高的经济学专业证书工科!【纯干货分享】
  • 文件系统-哈希结构文件
  • 食物分类案例优化 调整学习率和迁移学习
  • Paraverse平行云实时云渲染助力第82届威尼斯电影节XR沉浸式体验