GO学习之 数据库(mysql)

GO系列

1、GO学习之Hello World
2、GO学习之入门语法
3、GO学习之切片操作
4、GO学习之 Map 操作
5、GO学习之 结构体 操作
6、GO学习之 通道(Channel)
7、GO学习之 多线程(goroutine)
8、GO学习之 函数(Function)
9、GO学习之 接口(Interface)
10、GO学习之 网络通信(Net/Http)
11、GO学习之 微框架(Gin)
12、GO学习之 数据库(mysql)

文章目录

  • GO系列
  • 前言
  • 一、简介
  • 二、准备操作
  • 三、Insert 操作
  • 四、Delete 操作
  • 五、Update 操作
    • 5.1 获取数据库链接
    • 5.2 更新操作
  • 六、Select 操作
  • 五、事务
  • 六、总结

前言

按照公司目前的任务,go 学习是必经之路了,虽然行业卷,不过技多不压身,依旧努力!!!
数据持久化是必不可少的一部分,平日里开发,如果是专注于业务开发,那 99% 的工作也就是CRUD(增删改查)工程师了。
废话不多说,说了也没用,直接上手来操作,对数据库进行访问。

一、简介

对数据库操作,少不了各个语言对数据库操作的驱动,就像 JAVA 中有 mysql-driver 的驱动包,拉取下来就可以通过JDBC 对数据库操作了,当然 Spring、Mybatis 等框架也提供了对数据库很方便的操作。
那在 Go 中也是提供了驱动 github.com/go-sql-driver/mysql,我们通过 go get 拉取驱动来进行CRUD操作。
使用命令:go get github.com/go-sql-driver/mysql 来拉取驱动库。

二、准备操作

首先在 MYSQL 数据库创建一个测试库叫 go_demo,然后来添加一张 User 表来操作,脚本如下:

  • 新建表:
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`age` int(0) NULL DEFAULT NULL,`create_time` date NOT NULL,`update_time` date NOT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  • 插入测试数据
INSERT INTO `users` (name, address, age, create_time, update_time) VALUES ('悟空', '五指山下', 18, NOW(), NOW());
INSERT INTO `users` (name, address, age, create_time, update_time) VALUES ('唐僧', '大唐东土', 21, NOW(), NOW());
INSERT INTO `users` (name, address, age, create_time, update_time) VALUES ('八戒', '高老庄', 19, NOW(), NOW());
INSERT INTO `users` (name, address, age, create_time, update_time) VALUES ('沙森', '流沙河', 25, NOW(), NOW());
  • 查询数据
select * from users;

三、Insert 操作

下面的示例中,首先使用 database/sqlgithub.com/go-sql-driver/mysql 包来连接 MySQL 数据库,获取到一个连接示例 db, 再通过 db.Exec() 函数来执行 insert 语句,成功把 白龙马 指派到了师徒四人的队伍中。

package mainimport ("database/sql""fmt""log""time"_ "github.com/go-sql-driver/mysql"
)func main() {// 连接 MYSQL 数据库db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/go_demo")if err != nil {log.Fatal(err)}// defer 关键字来延迟关闭连接defer db.Close()// 插入数据insertSql := "INSERT INTO users (name, address, age, create_time, update_time) VALUES (?, ?, ?, ?, ?)"datetime := time.Now()_, insertErr := db.Exec(insertSql, "白龙马", "东海", 18, datetime, datetime)if insertErr != nil {log.Fatal(insertErr)}fmt.Println("插入数据成功!")
}

四、Delete 操作

下面的示例中,首先使用 database/sqlgithub.com/go-sql-driver/mysql 包来连接 MySQL 数据库,获取到一个连接示例 db, 再通过 db.Exec() 函数来执行 delete 语句,成功把 悟空 逐出了队伍。
可以看出来,从获取数据库连接到执行 SQL 语句,Go 代码基本一样的,想必定有框架做了此事了……

package mainimport ("database/sql""fmt""log"_ "github.com/go-sql-driver/mysql"
)func main() {// 连接mysql数据库db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/go_demo")if err != nil {log.Fatal(err)}defer db.Close()//删除悟空deleteSql := "delete from users where id = ?"_, deleteErr := db.Exec(deleteSql, 1)if deleteErr != nil {log.Fatal(deleteErr)}fmt.Println("删除成功!")
}

五、Update 操作

更新操作其实无外乎也是获取数据库连接,执行 update 语句,我们可以先封装一个公共的函数来获取数据库连接,在执行操作。

5.1 获取数据库链接

这里的包是 common, 在另一个包中,并且 Conn 首字母大写,表明外部包是可以调用的。

package commonimport ("database/sql""log"_ "github.com/go-sql-driver/mysql"
)func Conn() *sql.DB {// 连接mysql数据库db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/go_demo")if err != nil {log.Fatal(err)}return db
}

5.2 更新操作

下面案例,从上面封装的 common 包中通过 Conn() 函数获取数据库连接,再进行操作。
**注意:**这里需要用 common.Conn() 获取连接,不能用 *common.Conn() 获取,如果用 *common.Conn() 获取则在 后续的判断中 db != nil 出错:mismatched types sql.DB and untyped nil,因为db是一个指针类型,不能直接与 nil 进行比较。

package mainimport ("fmt""log""gotest.com/test/src/common"
)func main() {// 获取数据库连接db := common.Conn()if db != nil {defer db.Close()// 更新八戒的地址,不再是高老庄updateSql := "update users set address = ? where id = ?"_, updateErr := db.Exec(updateSql, "天上人间", 3)if updateErr != nil {log.Fatal(updateErr)}fmt.Println("更新成功!")} else {fmt.Println("获取数据库连接失败!")}
}

六、Select 操作

在下面的案例中:

  • 通过 自己封装的 common.Conn() 获取一个数据库链接
  • 利用 defer 关键词来延迟关闭链接
  • 通过 db.Query() 来执行一个查询
  • 循环遍历,rows.Next() 来判断是否有下一条记录,如果返回 true,大括号{}表示一个代码块,其中包含了每次迭代式要执行的代码。
  • {}中,可以对每条记录进行操作,比如利用 Scan() 来扫描将记录的值赋值给相应定义的变量。
  • 主要注意的是,rows.Scan(&id, &name…) 是指向 id、name 变量的指针,才能把记录中的值赋值给当前的变量。
package mainimport ("fmt""log""gotest.com/test/src/common"
)func main() {// 获取数据库连接db := common.Conn()selectSql := "select id,name,address,age from users"rows, err := db.Query(selectSql)if err != nil {log.Fatal(err)}// 延迟关闭数据库连接defer db.Close()// 遍历结果, rows是数据库查询结果的迭代器,Next()函数来判断是否下一条记录for rows.Next() {var id intvar name stringvar address stringvar age interr := rows.Scan(&id, &name, &address, &age)if err != nil {log.Fatal(err)}fmt.Println("id:", id, "name:", name, "address:", address, "age:", age)}
}

五、事务

下面示例中,使用db.Begin()来开启事务,本来要更新唐僧的地址为女儿国,唐僧也对女儿国王动心了,本来和女儿国王都说好了,玉帝哥哥陪国王白头到老(没头发如何白头到老),但是贫僧有要事在身,不得不离开,所以即便更新成功了,也得通过tx.Rollback()回滚回去。

package mainimport ("fmt""log""gotest.com/test/src/common"
)func main() {// 获取数据库连接db := common.Conn()if db != nil {defer db.Close()// 开启事务tx, beginErr := db.Begin()if beginErr != nil {log.Fatal(beginErr)}// 更新唐僧的地址,不再是东土大唐,留在了女儿国// 注意,这里要用事务 tx.Exec() 来执行操作updateSql := "update users set address = ? where id = ?"result, updateErr := db.Exec(updateSql, "女儿国", 2)count, _ := result.RowsAffected()// 如果影响行数大于 0if count > 0 {// 唐僧有使命在身,怎能为了儿女私情误了朕的大事tx.Rollback()fmt.Println("唐僧最终离开了女儿国!")return}if updateErr != nil {log.Fatal(updateErr)// 更新操作发生异常,事务回滚tx.Rollback()}// 提交事务commitErr := tx.Commit()if commitErr != nil {log.Fatal(commitErr)fmt.Println("更新提交失败!")}fmt.Println("更新成功!")} else {fmt.Println("获取数据库连接失败!")}
}
  • 运行前数据库记录如下:
    修改前
  • 运行结果如下:

可以看到,更新条数是 1,说明更新成功了!!!

PS D:\workspaceGo\src\database> go run .\updateTest.go
更新条数: 1
唐僧最终离开了女儿国!
2023/08/19 21:29:26 sql: transaction has already been committed or rolled back
exit status 1
  • 运行后数据库记录如下:
    运行后

注意:在使用 tx, beginErr := db.Begin()开启事务后,需要用 tx.Exec()来执行更新操作,这样后续的tx.Rollback()tx.Commit()操作才会生效。刚开始我就使用了db.Exec()来执行的更新操作,结果回滚就不生效,才发现犯了这等低级错误…

六、总结

此篇只对 Go 语言操作数据库进行简单的 CRUD 操作的示例,就像 JAVA 中用 JDBC 查库那样的基础操作,可发现基本就是通过获取的数据库链接通过函数进行对SQL的执行操作。

那 Go 操作 MySQL 有哪些优势呢?

  1. 高性能:Go 语言本身的设计目标就是高性能,所以也能够获得高性能的表现。
  2. 并发支持:Go 语言天生支持并发,可以轻松的实现并发的数据库操作,更加适合高并发的操作。
  3. 直接访问数据库:Go 语言通过标准库database/sql对SQL数据库直接访问的接口,允许直接操作数据库。

有哪些缺点呢?

  1. 生态系统相对较新:相对于其他语言,Go 语言在社区和工具等相对较新,不是很全面。
  2. ORM 支持有限:Go 语言的 ORM(对象关系映射)相对与其他语言成熟度较低,需要手动编写SQL更多。

第三方开源库用于操作 MySQL 数据库:

  1. database/sql:Go 语言标准库提供了database/sql包,支持多种数据库的操作。它提供了通用的接口的方法,让你能够进行基本的数据库操作。
  2. github.com/go-sql-driver/mysql:这是一个 MySQL 驱动,对 MySQL 数据库进行操作。
  3. github.com/jinzhu/gorm:GORM 是 Go 语言中一个流行的 ORM 框架,它 提供了对数据库的高级抽象,支持多种数据库。它可以简化数据库的操作,但是性能上有些损耗。
  4. github.com/go-xorm/xorm:XORM 是一个流行的 ORM 框架,它提供了对多种数据库的支持。它有一些独特的特性,适用于一些特定的场景。
  5. github.com/jmoiron/sqlx: SQLx 是 database/sql 的扩展,提供更方便的数据库操作方法。

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

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

相关文章

【vue3】同个页面引入多个图表组件实现自适应的方法

首先说明,此方案仅针对vue3项目在同一个页面引入了多个图表组件,因为我发现不能框架不同的引入,resize的写法还不同 window.addEventListener("resize", function() {...// 在此处重新调用即可 }以下是具体写法: 循环…

前端实习第五周周记

前言 每一天做了什么还是要记录一下,不然过两天后就会发现,慢慢遗忘自己的收获与做过的东西。 这周做的是医学检验系统的样本库部分。由于是公司的代码所以不能交代具体,那么久聊一下每天具体做了些什么以及我的一些收获。 周一 周一上午…

【C++】四种强制类型转换

内容来自《C Primer(第5版)》4.11.3 显示转换、6.4 函数重载、19.2.1 dynamic_cast运算符 目录 1. static_cast 2. const_cast 3. reinterpret_cast 4. dynamic_cast 4.1 指针类型的dynamic_cast 4.2 引用类型的dynamic_cast C语言的强制类型转换&…

Unity进阶–通过PhotonServer实现人物选择和多人同步–PhotonServer(四)

文章目录 Unity进阶–通过PhotonServer实现人物选择和多人同步–PhotonServer(四)服务端客户端 Unity进阶–通过PhotonServer实现人物选择和多人同步–PhotonServer(四) 服务端 服务端结构如下: UserModel using System; using System.Collections.Generic; usin…

Qt 编译使用Bit7z库接口调用7z.dll、7-Zip.dll解压压缩常用Zip、ISO9660、Wim、Esd、7z等格式文件(二)

修改qt5 7zip源码编译及使用(含展示进度)一文中的封装类ZlibHelper代码类,继承多线程,使解压,压缩时进度条不影响界面,同时添加压缩文件中的文件预览功能,建议直接看源码 导读 相关代码内容扩展预览内容时获取文件修改…

深入探究arthas的命令

Arthas是一个Java诊断工具,用于在线诊断Java应用程序,以便更轻松地监控和分析应用程序的性能和行为。Arthas中有许多用于诊断Java应用程序的命令。 1. jvm 和 dashboard 命令的区别: jvm:该命令用于显示当前的JVM信息&#xff0c…

pointnet C++推理部署--tensorrt框架

classification 如上图所示,由于直接export出的onnx文件有两个输出节点,不方便处理,所以编写脚本删除不需要的输出节点193: import onnxonnx_model onnx.load("cls.onnx") graph onnx_model.graphinputs graph.inpu…

【C++】C++入门基础:引用详解

本篇继续分享关于C入门的相关知识,有关命名空间、缺省参数和函数重载的部分欢迎阅读我的上一篇文章【C】C入门基础详解(1)_王笃笃的博客-CSDN博客 继续我们的学习 引用 在C语言中我们接触过指针,很多人都或多或少为他感到头痛过…

使用SSH隧道将Ubuntu云服务器Jupyter Notebook端口映射到本地

本文主要实现了在Ubuntu云服务器后台运行Jupyter Notebook,并使用SSH隧道将服务器端口映射到本地 1. 生成配置文件 运行以下命令生成Jupyter Notebook的配置文件: jupyter notebook --generate-config这将在用户主目录下生成一个名为.jupyter的文件夹&…

MySQL索引ES索引

MySQL MySQL索引的种类 按照索引列值的唯一性:索引可分为唯一索引和非唯一索引; 唯一索引:此索引的每一个索引值只对应唯一的数据记录,对于单列唯一性索引,这保证单列不包含重复的值。对于多列唯一性索引,保证多个值的组合不重复。主键索引是唯一索引的特定类型。该索引…

【傅里叶级数与傅里叶变换】数学推导——3、[Part4:傅里叶级数的复数形式] + [Part5:从傅里叶级数推导傅里叶变换] + 总结

文章内容来自DR_CAN关于傅里叶变换的视频,本篇文章提供了一些基础知识点,比如三角函数常用的导数、三角函数换算公式等。 文章全部链接: 基础知识点 Part1:三角函数系的正交性 Part2:T2π的周期函数的傅里叶级数展开 P…

【Rust日报】2023-08-18 RustShip:一个新的 Rust 播客

探索 Rust 编译器基准测试套件 在最近关于 Rust 编译器 CI(持续集成)和基准测试基础设施的文章中,作者承诺写一篇关于运行时基准测试的博客文章,这是 Rust 编译器基准测试套件的新补充。然而,在这样做之前,…

信息熵,信息增益,增益率的理解

西瓜数据集D如下: 编号色泽根蒂敲声纹理脐部触感好瓜1青绿蜷缩浊响清晰凹陷硬滑是2乌黑蜷缩沉闷清晰凹陷硬滑是3乌黑蜷缩浊响清晰凹陷硬滑是4青绿蜷缩沉闷清晰凹陷硬滑是5浅白蜷缩浊响清晰凹陷硬滑是6青绿稍蜷浊响清晰稍凹软粘是7乌黑稍蜷浊响稍糊稍凹软粘是8乌黑稍蜷浊响清晰…

回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测(多指标,多图)效果一览基…

aardio窗体缩放自动匹配批量生成plus实例

import win.ui; /*DSG{{*/ var winform win.form(text"窗体缩放批量生成plus";right759;bottom469;bgcolor15780518) winform.add( custom{cls"custom";text"自定义控件";left3;top6;right753;bottom460;ah1;aw1;bgcolor15780518;z1} ) /*}}*//…

UML基础模型

目录 1.抽象类2.接口3.继承4.实现接口5.关联关系6.聚合关系7.合成(组合)关系8.依赖关系 1.抽象类 矩形框代表一个类(Class)。 类图分为三层: 第一层显示类的名称,如果是抽象类,就用斜体显示&am…

操作系统的体系结构、内核、虚拟机

🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaweb 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 操作系统结构 一、操作系统体系结构1.1操作系统的内核1.1.…

TiDB 多集群告警监控-中章-融合多集群 Grafana

作者: longzhuquan 原文来源: https://tidb.net/blog/ac730b0f 背景 随着公司XC改造步伐的前进,越来越多的业务选择 TiDB,由于各个业务之间需要物理隔离,避免不了的 TiDB 集群数量越来越多。虽然每套 TiDB 集群均有…

Educational Codeforces Round 2

目录 A. Extract Numbers B. Queries about less or equal elements C. Make Palindrome E. Lomsat gelral A. Extract Numbers 题意:太多不想翻译 思路:字符串模拟,我们使用一个临时变量t去储存每个符号直接的字符串,同时需…

0.flink学习资料

论文: (1)google dataflow model 下载链接:p1792-Akidau.pdf (vldb.org) Akidau T, Bradshaw R, Chambers C, et al. The dataflow model: a practical approach to balancing correctness, latency, and cost in massive-scal…