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.rhkb.cn/news/97305.html

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

相关文章

【C++】stack/queue/优先级队列的模拟实现

目录 1. stack/queue1.1 模拟实现 2. 优先级队列2.1 模拟实现2.2 仿函数 1. stack/queue stack文档说明 queue文档说明 stack和queue被称为容器适配器。 容器适配器是什么? 它是一种特殊的容器类型,通过封装已有的容器类型来提供特定功能的接口函数&a…

使用Nginx调用网关,然后网关调用其他微服务

问题前提:目前我的项目是已经搭建了网关根据访问路径路由到微服务,然后现在我使用了Nginx将静态资源都放在了Nginx中,然后我后端定义了一个接口访问一个html页面,但是html页面要用到静态资源,这个静态资源在我的后端是…

关于es中索引,倒排索引的理解

下面是我查询进行理解的东西 也就是说我们ES中的索引就相当于我们mysql中的数据库表,索引库就相当于我们的数据库,我们按照mapping规则会根据相应的字段(index为true默认)来创建倒排索引,这个倒排索引就相当于我们索引…

QT-Mysql数据库图形化接口

QT sql mysqloper.h qsqlrelationaltablemodelview.h /************************************************************************* 接口描述:Mysql数据库图形化接口 拟制: 接口版本:V1.0 时间:20230727 说明:支…

【ARM Linux 系统稳定性分析入门及渐进12 -- GDB内存查看命令 “x“(examine)】

文章目录 gdb 内存查看命令 examine 上篇文章:ARM Linux 系统稳定性分析入门及渐进11 – GDB( print 和 p 的使用| 和 ::的使用|ptype|{<type>} <addr> ) gdb 内存查看命令 examine examine是…

【数据结构】如何用队列实现栈?图文详解(LeetCode)

LeetCode链接:225. 用队列实现栈 - 力扣(LeetCode) 本文默认读者已经掌握栈与队列的基本知识 或者先看我的另一篇博客:【数据结构】栈与队列_字节连结的博客-CSDN博客 做题思路 由于我们使用的是C语言,不能直接使用队…

​Kubernetes的演变:从etcd到分布式SQL的过渡

DevRel领域专家Denis Magda表示,他偶然发现了一篇解释如何用PostgreSQL无缝替换etcd的文章。该文章指出,Kine项目作为外部etcd端点,可以将Kubernetes etcd请求转换为底层关系数据库的SQL查询。 受到这种方法的启发,Magda决定进一步…

react-native-webview RN和html双向通信

rn登录后得到的token需要传递给网页,js获取到的浏览器信息需要传递给rn RN Index.js: import React from react import { WebView } from react-native-webview import useList from ./useListexport default function Index(props) {const { uri, jsCode, webVie…

【MySQL系列】--初识数据库

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …

在ubuntu中将dict.txt导入到数据库sqlite3

将dict.txt导入到数据库 #include <head.h> #include <sqlite3.h> int do_insert(int i,char *str,sqlite3 *db); int main(int argc, const char *argv[]) {//创建泵打开一个数据库sqlite3 *db NULL;if(sqlite3_open("./my.db",&db) ! SQLITE_OK){…

使用IDM下载视频出现“由于法律原因,IDM无法下载...

一、问题描述 由于法律原因,IDM无法下载..,如图: 二、原因分析 下载该IDM抓取的M3U8文件,查看其中的内容发现 : #EXT-X-KEY 字段已经写明了加密方式是AES-128,包含一个URI和IV值 #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:8 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-KEY:…

Cpp学习——list的模拟实现

目录 一&#xff0c;实现list所需要包含的三个类 二&#xff0c;三个类的实现 1.list_node 2.list类 3.iterator_list类 三&#xff0c;功能实现 1.list类里的push_back() 2.iterator类里的运算符重载 3&#xff0c;list类里面的功能函数 1.insert&#xff08;&#xff…

2023国赛数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…

Linux常用命令——dig命令

在线Linux命令查询工具 dig 域名查询工具 补充说明 dig命令是常用的域名查询工具&#xff0c;可以用来测试域名系统工作是否正常。 语法 dig(选项)(参数)选项 <服务器地址>&#xff1a;指定进行域名解析的域名服务器&#xff1b; -b<ip地址>&#xff1a;当主…

Log4net在.Net Winform项目中的使用

引言&#xff1a; Log4net是一个流行的日志记录工具&#xff0c;可以帮助开发人员在应用程序中实现高效的日志记录。本文将提供一个详细的分步骤示例&#xff0c;来帮助您在.Net Winform项目中使用Log4net。 目录 一、安装Log4net二、配置Log4net三、在项目中使用Log4net四、初…

深入探索:Kali Linux 网络安全之旅

目录 前言 访问官方网站 导航到下载页面 启动后界面操作 前言 "Kali" 可能指的是 Kali Linux&#xff0c;它是一种基于 Debian 的 Linux 发行版&#xff0c;专门用于渗透测试、网络安全评估、数字取证和相关的安全任务。Kali Linux 旨在提供一系列用于测试网络和…

uniapp的uview-plus组件库的导入

uniapp的vue3中使用uview-plus组件库。在插件市场中找到该组件并点击如下所示绿色按钮&#xff0c;弹出弹窗选择要导入的项目后&#xff0c;就会在uni_modules文件中生成如下文件内容 关于插件的下载区别&#xff0c;可参考&#xff1a;https://uniapp.dcloud.net.cn/compone…

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

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

(三)行为型模式:3、解释器模式(Interpreter Pattern)(C++示例)

目录 1、解释器模式&#xff08;Interpreter Pattern&#xff09;含义 2、解释器模式的UML图学习 3、解释器模式的应用场景 4、解释器模式的优缺点 5、C实现解释器模式的实例 1、解释器模式&#xff08;Interpreter Pattern&#xff09;含义 解释器模式&#xff08;Interp…