GO从入门到进阶教程系列 - 研发高性能ORM框架mysql管理多数据源篇

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:   ↵       上一篇教程我们了解到了基础的GO语法,今天我们来学习如何使用GO开发一个通用的mysql管理器,下面就直接进入步骤环节,代码需要承接上一篇教程的,如有疑问请查看上一篇教程技术版权归属 广州市金狮网络科技有限公司 (https://kingc.
  

       上一篇教程我们了解到了基础的GO语法,今天我们来学习如何使用GO开发一个通用的mysql管理器,下面就直接进入步骤环节,代码需要承接上一篇教程的,如有疑问请查看上一篇教程

技术版权归属 广州市金狮网络科技有限公司 (https://kingc.cn/) ,如需商用请联系公司

1. 编写一个多数据源实例的管理器对象,以及改造下之前的DBConfig对象

// 连接管理器
type RDBManager struct {
	OpenTx   bool    // 是否开启事务
	DsName string  // 数据源名称
	Db     *sql.DB // 非事务实例
	Tx     *sql.Tx // 事务实例
	Errors []error // 操作过程中记录的错误
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
// 数据库配置
type DBConfig struct {
	DsName   string // 数据源名称
	Host     string // 地址IP
	Port     int    // 数据库端口
	Database string // 数据库名称
	Username string // 账号
	Password string // 密码
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2. 编写初始化多个数据源配置的方法,并改造下我们之前的NewMysql方法

// 初始化数据库实例
func NewMysql(conf DBConfig) (*sql.DB, error) {
	// 定义占位符字符串,使用配置值替换%s和%d
	link := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", conf.Username, conf.Password, conf.Host, conf.Port, conf.Database)
	// 打开mysql获得实例对象
	db, err := sql.Open("mysql", link)
	// 打开mysql失败,返回nil对象,以及返回err对象
	if err != nil {
		return nil, errors.New("mysql初始化失败: " + err.Error())
	}
	// 打开mysql成功返回db对象,err=nil
	return db, nil
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
var (
	MASTER = "MASTER"	// 默认主数据源
	RDBs   = map[string]*RDBManager{} // 初始化时加载数据源到集合
)

// 初始化多个数据库配置文件
func BuildByConfig(input ...DBConfig) {
	if len(input) == 0 {
		panic("数据源配置不能为空")
	}
	for _, v := range input {
		db, err := NewMysql(v)
		panic(err)
		if len(v.DsName) == 0 {
			v.DsName = MASTER
		}
		rdb := &RDBManager{
			Db:     db,
			DsName: v.DsName,
		}
		RDBs[v.DsName] = rdb
	}
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3. 编写获取数据源的方法,包含是否开启事务,数据源名称参数

// 获取数据源,并控制是否开启事务
func GetDB(openTx bool, ds ...string) (*RDBManager, error) {
	dsName := MASTER
	if len(ds) > 0 && len(ds[0]) > 0 {
		dsName = ds[0]
	}
	rt := RDBs[dsName]
	rdb := &RDBManager{
		OpenTx: openTx,
		Db:     rt.Db,
		DsName: rt.DsName,
		Errors: []error{},
	}
	// 如设置事务,则初始化事务实例
	if rdb.OpenTx {
		tx, err := rdb.Db.Begin()
		if err != nil {
			return nil, errors.New("开启事务失败:" + err.Error())
		}
		rdb.Tx = tx
	}
	return rdb, nil
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

4. 编写释放数据库资源,并提交事务的方法

// 释放资源并提交事务
func (self *RDBManager) Close() {
	if self.OpenTx { // 开启事务操作逻辑
		if len(self.Errors) > 0 { // 如产生异常则回滚事务
			self.Tx.Rollback()
		} else {
			self.Tx.Commit() // 如无异常则提交事务
		}
	}
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==


5. 使用获取的数据源进行保存数据操作,我们改造下之前的CRUD方法

// 通过管理器开启事务保存数据
func (self *RDBManager) CRUD1() error {
	// 编写需要执行的sql
	createSql := "insert test_user(username, password, age, sex) values(?,?,?,?)"
	// 预编译sql,事务模式
	stmt, err := self.Tx.Prepare(createSql)
	if err != nil {
		return errors.New("预编译失败: " + err.Error())
	}
	// 提交编译sql对应参数
	ret, err := stmt.Exec("zhangsan", "123456", 18, 1)
	if err != nil {
		return errors.New("提交数据失败: " + err.Error())
	}
	// 保存成功后获取自增ID
	fmt.Println(ret.LastInsertId())
	return nil
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

6. 编写单元测试用例

// 单元测试
func TestCRUD1(t *testing.T) {
	// 数据源配置
	conf := DBConfig{
		DsName:   "test",
		Host:     "127.0.0.1",
		Port:     3306,
		Database: "test",
		Username: "root",
		Password: "123456",
	}
	// 初始化数据源
	BuildByConfig(conf)
	// 获取test数据源
	rdb, err := GetDB(true, "test")
	if err != nil {
		panic(err)
	}
	// 释放资源
	defer rdb.Close()
	// 执行保存数据方法
	if err := rdb.CRUD1(); err != nil {
		panic(err)
	}
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

上面我们已经明白了自定义数据源管理器如何实现,通过示例演示操作,下一篇文章我会讲解如何封装对象转sql入库,敬请期待!

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
23天前
|
Go 开发者
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
|
23天前
|
存储 监控 关系型数据库
轻松入门Mysql:MySQL性能优化与监控,解锁进销存系统的潜力(23)
轻松入门Mysql:MySQL性能优化与监控,解锁进销存系统的潜力(23)
|
23天前
|
SQL 数据可视化 关系型数据库
轻松入门MySQL:深入探究MySQL的ER模型,数据库设计的利器与挑战(22)
轻松入门MySQL:深入探究MySQL的ER模型,数据库设计的利器与挑战(22)
105 0
|
23天前
|
存储 关系型数据库 MySQL
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
|
23天前
|
存储 关系型数据库 MySQL
轻松入门MySQL:揭秘MySQL游标,数据处理的神秘利器(16)
轻松入门MySQL:揭秘MySQL游标,数据处理的神秘利器(16)
|
19天前
|
存储 关系型数据库 MySQL
MySQL基础入门:数据库操作全攻略
MySQL基础入门:数据库操作全攻略
48 0
|
17天前
|
Go
go语言中的数据类型
go语言中的数据类型
13 0
|
4天前
|
数据采集 存储 Go
使用Go语言和chromedp库下载Instagram图片:简易指南
Go语言爬虫示例使用chromedp库下载Instagram图片,关键步骤包括设置代理IP、创建带代理的浏览器上下文及执行任务,如导航至用户页面、截图并存储图片。代码中新增`analyzeAndStoreImage`函数对图片进行分析和分类后存储。注意Instagram的反爬策略可能需要代码适时调整。
使用Go语言和chromedp库下载Instagram图片:简易指南
|
23天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
|
1天前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello("Alice")`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
10 1