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,一经查实,立即删除!

相关文章

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

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

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的文件夹&…

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

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

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

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

回归预测 | 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 集群均有…

Gateway网关路由以及predicates用法(项目中使用场景)

1.Gatewaynacos整合微服务 服务注册在nacos上,通过Gateway路由网关配置统一路由访问 这里主要通过yml方式说明: route: config: #type:database nacos yml data-type: yml group: DEFAULT_GROUP data-id: jeecg-gateway-router 配置路由:…

宁德时代与陕汽签署十年战略合作协议,助力商用车电动化进程

据报道,宁德时代新能源科技股份有限公司与陕西汽车控股集团有限公司已经签署了一项为期十年的战略合作协议。双方的合作旨在推动商用车电池技术的发展,并面向商用车全领域应用。 这次战略合作具有重要意义,为宁德时代和陕汽启动了全面合作的序…

2021年3月全国计算机等级考试真题(C语言二级)

2021年3月全国计算机等级考试真题(C语言二级) 第1题 算法空间复杂度的度量方法是() A. 算法程序的长度 B. 算法所处理的数据量 C. 执行算法所需要的工作单元 D. 执行算法所需要的存储空间 正确答案:D 第2题 下列叙…

【自创】关于前端js的“嵌套地狱”的遍历算法

欢迎大家关注我的CSDN账号 欢迎大家关注我的哔哩哔哩账号:卢淼儿的个人空间-卢淼儿个人主页-哔哩哔哩视频 此saas系统我会在9月2号之前,在csdn及哔哩哔哩上发布成套系列教学视频。敬请期待!!! 首先看图 这是我们要解…

Spring Boot 知识集锦之Spring-Batch批处理组件详解

文章目录 0.前言1.参考文档2.基础介绍2.1. 核心组件 3.步骤3.1. 引入依赖3.2. 配置文件3.3. 核心源码 4.示例项目5.总结 0.前言 背景: 一直零散的使用着Spring Boot 的各种组件和特性,从未系统性的学习和总结,本次借着这个机会搞一波。共同学…

无涯教程-TensorFlow - TensorBoard可视化

TensorFlow包含一个可视化工具,称为TensorBoard,它用于分析数据流图,还用于了解机器学习模型。 TensorBoard的重要功能包括查看有关垂直对齐的任何图形的参数和详细信息的不同类型统计的视图。 深度神经网络包括多达36,000个节点…

HCIP——VLAN实验2

一.实验要求 1.PC1/3的接口均为access模式,且属于van2,在同一网段 2.PC2/4/5/6的IP地址在同一网段,与PC1/3不在同一网段 3.PC2可以访问4/5/6,PC4不能访问5/6,PC5不能访问PC6 4.所有PC通过DHCP获取ip地址,PC…

《合成孔径雷达成像算法与实现》Figure3.10

代码复现如下: clc clear close all% 参数设置 TBP 100; % 时间带宽积 T 7.2e-6; % 脉冲持续时间 t_0 1e-6; % 脉冲回波时延% 参数计算 B TBP/T; …

unity 之Transform组件(汇总)

文章目录 理论指导结合例子 理论指导 当在Unity中处理3D场景中的游戏对象时,Transform 组件是至关重要的组件之一。它管理了游戏对象的位置、旋转和缩放,并提供了许多方法来操纵和操作这些属性。以下是关于Transform 组件的详细介绍: 位置&a…