02 Go语言操作MySQL基础教程_20240729 课程笔记
概述
如果您没有Golang的基础,应该学习如下前置课程。
- Golang零基础入门
- Golang面向对象编程
- Go Web 基础
- Go语言开发REST API接口_20240728
基础不好的同学每节课的代码最好配合视频进行阅读和学习,如果基础比较扎实,则阅读本教程巩固一下相关知识点即可,遇到不会的知识点再看视频。
视频课程
最近发现越来越多的公司在用Golang了,所以精心整理了一套视频教程给大家,这个是其中的第5部,后续还会有很多。
视频已经录制完成,完整目录截图如下:

打个小广告,目前处于特价阶段,一节课只需要1块钱,29节课只需要29元哦。如果有需要,请前往我的淘宝店铺“Python私教”下单。
课程目录
- 01 使用Go语言连接MySQL
- 02 ySQL官方库的拉取和使用
- 03 打开和关闭连接
- 04 创建用户表
- 05 新增用户
- 06 根据ID查询用户
- 07 查询所有的用户
- 08 根据ID修改用户
- 09 根据ID删除用户
- 10 使用预处理查询所有的用户
- 11 使用预处理新增用户
- 12 事务的介绍和使用
- 13 回顾RESTAPI接口开发
- 14 开发获取所有用户信息的接口
- 15 使用HTTP客户端测试获取所有用户接口
- 16 开发和测试根据ID获取用户的接口
- 17 开发和测试新增用户的接口
- 18 开发和测试根据ID修改用户的接口
- 19 开发根据ID删除用户的接口
- 20 新增数据的SQL代码分析
- 21 实现MySQL通用新增数据的方法
- 22 测试MySQL通用新增数据的方法
- 23 封装并测试通用的修改数据的方法
- 24 封装并测试通用的删除方法
- 25 封装通用的查询所有数据的方法
- 26 将查询的数据转换为字典
- 27 优化查询所有用户的方法
- 28 实现根据ID查询并进行测试
- 29 总结
精品代码
完整代码实在是太多了,放弃了给大家分享完整代码的想法,这里摘录一些个人认为比较精品的代码。
封装将SQL查询结果转换为字典的方法
这个方法想了很久,也查阅了大量的资料,最终被实现了。
代码封装如下:
package zdpgo_mcrudimport ("database/sql""errors""fmt""strings"
)func GetBy(db *sql.DB,tableName string,columns []string,conditions map[string]interface{},
) (data []map[string]interface{}, err error) {if db == nil {err = errors.New("db is nil")return}if tableName == "" {err = errors.New("tableName is empty")return}var columnStr stringif columns == nil || len(columns) == 0 {columnStr = "*"} else {columnStr = strings.Join(columns, ",")}sqlStr := fmt.Sprintf("select %s from %s",columnStr,tableName,)// 构造查询条件whereValues := []interface{}{}whereKeys := []string{}if conditions != nil && len(conditions) > 0 {// select * from user// select * from user where k=vfor k, v := range conditions {whereKeys = append(whereKeys, fmt.Sprintf("%s=?", k))whereValues = append(whereValues, v)}whereStr := strings.Join(whereKeys, ",")sqlStr += " where " + whereStr}// 准备执行查询var stmt *sql.Stmtstmt, err = db.Prepare(sqlStr)if err != nil {fmt.Println(err)return}defer stmt.Close()// 执行查询var rows *sql.Rowsrows, err = stmt.Query(whereValues...)defer rows.Close()if rows == nil {err = errors.New("rows is nil")return}count := len(columns) // 列的个数values := make([]interface{}, count) // 一组数据的值valuePtrs := make([]interface{}, count) // 一组数据的值的对应地址for rows.Next() {for i := 0; i < count; i++ {valuePtrs[i] = &values[i] // 将列的数据的值的地址取出来,赋值给地址值}err = rows.Scan(valuePtrs...) // 获取各列的值,放在对应地址中if err != nil {return}item := make(map[string]interface{}) // 构建列名和值的对应关系 {name:张三,age:22}for i, col := range columns {var v interface{} // 临时值val := values[i] // 对应的值b, ok := val.([]byte) // 判断能不能转换为字节数组,实际上就是判断是不是字符串if ok {v = string(b) // 转换为字符串} else {v = val}item[col] = v}data = append(data, item)}return
}
使用方法如下:
package mainimport ("database/sql""fmt""github.com/zhangdapeng520/zdpgo_mcrud"_ "github.com/zhangdapeng520/zdpgo_mysql"
)var (db *sql.DBerr error
)func initMySQL() {dbUrl := "root:root@tcp(127.0.0.1:3306)/test"db, err = sql.Open("mysql", dbUrl)if err != nil {fmt.Println(err)return}
}func closeMySQL() {db.Close()
}func main() {initMySQL()defer closeMySQL()err = db.Ping()if err != nil {fmt.Println(err)return}conditions := map[string]interface{}{"id": 1,}data, err := zdpgo_mcrud.GetBy(db,"user",[]string{"id", "name", "age"},conditions,)if err != nil {fmt.Println(err)return}fmt.Println(data)
}
有了这个方法以后,我们就有了一个通用的查询方法,不用再写重复的SQL语句了。
实现用户增删改查REST API接口
这个需要大家学习我之前的前置课,就是那个REST API的基础课。
再结合这个课程的MYSQL基础知识,就可以开发了。
服务端代码如下:
package mainimport ("database/sql""fmt""github.com/zhangdapeng520/zdpgo_httprouter"_ "github.com/zhangdapeng520/zdpgo_mysql""net/http""time"
)var (db *sql.DBerr error
)func initMySQL() {dbUrl := "root:root@tcp(127.0.0.1:3306)/test"db, err = sql.Open("mysql", dbUrl)if err != nil {fmt.Println(err)return}
}func closeMySQL() {db.Close()
}type User struct {Id int64 `json:"id"`Name string `json:"name"`Age int `json:"age"`
}func DbGetAllUser() []User {var users []UsersqlStr := "select id,name,age from user"var stmt *sql.Stmtstmt, err = db.Prepare(sqlStr)if err != nil {fmt.Println(err)return users}defer stmt.Close()var rows *sql.Rowsrows, err = stmt.Query()defer rows.Close()// 读取for rows.Next() {var (uid int64name stringage int)err = rows.Scan(&uid, &name, &age)if err != nil {fmt.Println(err)return users}users = append(users, User{uid, name, age})fmt.Println(uid, name, age)}return users
}
func DbGetUser(uid string) []User {var users []UsersqlStr := "select id,name,age from user where id=?"var stmt *sql.Stmtstmt, err = db.Prepare(sqlStr)if err != nil {fmt.Println(err)return users}defer stmt.Close()var rows *sql.Rowsrows, err = stmt.Query(uid)defer rows.Close()// 读取for rows.Next() {var (uid int64name stringage int)err = rows.Scan(&uid, &name, &age)if err != nil {fmt.Println(err)return users}users = append(users, User{uid, name, age})fmt.Println(uid, name, age)}return users
}func DbAddUser(name string, age int) int64 {sqlStr := "insert into user(name,age) values (?,?)"var stmt *sql.Stmtstmt, err = db.Prepare(sqlStr)if err != nil {fmt.Println(err)return -1}defer stmt.Close()var result sql.Resultresult, err = stmt.Exec(name, age)if err != nil {fmt.Println(err)return -1}var uid int64uid, err = result.LastInsertId()if err != nil {fmt.Println(err)return -1}fmt.Println("插入成功,ID是:", uid)return uid
}func DbUpdateUser(name string, age int, id string) int64 {sqlStr := "update user set name=?, age=? where id=?"var result sql.Resultresult, err = db.Exec(sqlStr, name, age, id)if err != nil {fmt.Println(err)return 0}var rowNum int64rowNum, err = result.RowsAffected()if err != nil {fmt.Println(err)return 0}fmt.Printf("更新 %d 条数据成功\n", rowNum)return rowNum
}func DbDeleteUser(id string) int64 {sqlStr := "delete from user where id=?"var result sql.Resultresult, err = db.Exec(sqlStr, id)if err != nil {fmt.Println(err)return 0}var rowNum int64rowNum, err = result.RowsAffected()if err != nil {fmt.Println(err)return 0}fmt.Printf("删除 %d 条数据成功\n", rowNum)return rowNum
}func RouterGetAllUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {users := DbGetAllUser()zdpgo_httprouter.ResponseSuccess(w, &users)
}func RouterGetUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {uid := ps.ByName("id")users := DbGetUser(uid)var user Userif len(users) > 0 {user = users[0]}zdpgo_httprouter.ResponseSuccess(w, &user)
}func RouterAddUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {var user Userzdpgo_httprouter.GetJson(r, &user)uid := DbAddUser(user.Name, user.Age)user.Id = uidzdpgo_httprouter.ResponseSuccess(w, &user)
}
func RouterUpdateUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {var user Userzdpgo_httprouter.GetJson(r, &user)uid := ps.ByName("id")updateRows := DbUpdateUser(user.Name, user.Age, uid)zdpgo_httprouter.ResponseSuccess(w, updateRows)
}
func RouterDeleteUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {uid := ps.ByName("id")updateRows := DbDeleteUser(uid)zdpgo_httprouter.ResponseSuccess(w, updateRows)
}func main() {initMySQL()defer closeMySQL()err = db.Ping()if err != nil {fmt.Println(err)return}router := zdpgo_httprouter.New()router.GET("/user", RouterGetAllUser)router.GET("/user/:id", RouterGetUser)router.POST("/user", RouterAddUser)router.PUT("/user/:id", RouterUpdateUser)router.DELETE("/user/:id", RouterDeleteUser)server := &http.Server{Addr: "0.0.0.0:8888",Handler: router,ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,}server.ListenAndServe()
}
客户端代码也有增删改查的,这里以根据ID删除为例子。
package mainimport ("fmt""github.com/zhangdapeng520/zdpgo_httprouter""io"
)func main() {targetUrl := "http://localhost:8888/user/3"data := map[string]interface{}{}resp, err := zdpgo_httprouter.SendJson("DELETE", targetUrl, data)if err != nil {fmt.Println(err)return}body := resp.BodybodyBytes, err := io.ReadAll(body)if err != nil {fmt.Println(err)return}fmt.Println(string(bodyBytes))
}
总结
本套教程主要讲解Go语言操作MySQL的基础知识,同时还讲解了如何结合之前学习的REST API的基础知识,开发用户增删改查的API接口,最后还通过对MySQL通用方法的封装,让大家学习到MySQL的进阶使用技巧。
如果您需要完整的源码,打赏20元即可。
人生苦短,我用Python,我是您身边的Python私教~
相关文章:
02 Go语言操作MySQL基础教程_20240729 课程笔记
概述 如果您没有Golang的基础,应该学习如下前置课程。 Golang零基础入门Golang面向对象编程Go Web 基础Go语言开发REST API接口_20240728 基础不好的同学每节课的代码最好配合视频进行阅读和学习,如果基础比较扎实,则阅读本教程巩固一下相…...
相交链表 - 力扣(LeetCode)C语言
160. 相交链表 - 力扣(LeetCode) (点击前面链接即可查看题目) 一、题目 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始…...
【Python】基础学习技能提升代码样例3:JSON文本处理
对json的处理,无非是编码和解码两部分 编码:将python数据结构转换为json字符串解码: 将json字符串转换为python数据结构 另外,还有.json文件的读写 一、编码 json.dumps(obj, *, skipkeysFalse, ensure_asciiTrue, check_circularTrue, a…...
最新Yiso智云搜索引擎系统源码/开源PHP源码/修复版
源码简介: 最新Yiso智云搜索引擎系统源码/开源PHP源码/修复版。Yiso 是一个性能非常好的搜索引擎,不仅免费开源,还能当作收录网址的平台来用呢!只需要输入关键词,就能轻松找到相关的搜索结果内容。 1、Yiso 用的是自…...
Anconda 快速常用命令简洁版
目的:简单清楚的使用基本的conda 命令 可能需求 查看项目中的虚拟环境及依赖是否满足需求操作新环境来满足项目或者论文的实现 Anconda 常用命令 conda 查看基础命令1. 进入Anaconda 环境2. 查看版本3.查看有哪些虚拟环境4.激活虚拟环境5. 进入虚拟环境查看6. 退出…...
Android 系统启动动画
一、接着我们把 bootanimation.zip 动画文件 预制到 /system/media/ 目录下: 二、目录/system/media/bootanimation.zip PRODUCT_COPY_FILES \$(LOCAL_PATH)/bootanimation.zip:/system/media/bootanimation.zipPRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST \ /…...
解决antd打开modal时页面自动跳到顶部问题
问题原因:antd的样式中有一行,如下样式代码,这行代码导致了在本来有滚动条的页面底部触发modal弹出时,会自动滚动到页面顶部。 html {overflow-y: scroll; } 解决办法:删除这行代码、或者将html的overflow-y属性改成…...
什么是等保测评2.0,等保测评如何定级
在信息化时代,网络安全已成为国家安全的重要组成部分。为了应对日益复杂的网络安全形势,我国推出了网络安全等级保护制度,其中等保测评是评估信息系统安全防护能力的关键环节。本文将深入探讨等保2.0的测评流程和定级标准,以揭示其…...
【嵌入式英语教程--6】C语言中的数组与指针
C语言中的数组与指针 英文原文 Arrays and pointers are fundamental concepts in the C programming language. An array is a collection of elements of the same data type stored in contiguous memory locations. Arrays can be used to store and manipulate sequence…...
RocketMQ 中的同步发送
在现代分布式系统中,消息队列是实现异步通信和解耦的重要组件。Apache RocketMQ 是一款高性能、高吞吐量的分布式消息中间件,广泛应用于电商、金融等领域。本文将详细介绍 RocketMQ 中的同步发送,包括其原理、应用场景、代码示例及注意事项。…...
c语言指针2
文章目录 一、void * 指针二、const关键字1.const修饰变量2.const修饰指针变量2. 1 const放在*的右边2. 2 const放在*的左边2. 3 总结 三、指针的运算3. 1指针的加减运算3. 2 指针 - 指针3. 3 指针的关系运算 四、野指针4. 1 什么叫野指针?4. 1 野指针的成因4.1.1 指…...
十七、openCV教程 图像轮廓
一、图像轮廓 图像轮廓是具有相同颜色或灰度的连续点的曲线.轮廓在形状分析和物体的检测和识别中很有用。 轮廓的作用:.用于图形分析、物体的识别和检测 注意点: 为了检测的准确性,需要先对图像进行二值化或Canny操作。 画轮廓时会修改输入的图像,如…...
基于视觉的语义匹配见多了,那基于雷达的呢?
论文题目: LiDAR-based HD Map Localization using Semantic Generalized ICP with Road Marking Detection 论文作者: Yansong Gong, Xinglian Zhang, Jingyi Feng, Xiao He and Dan Zhang 作者单位:北京驭势科技有限公司 导读ÿ…...
01、爬虫学习入门
爬虫:通过编写程序,来获取获取互联网上的资源 需求:用程序模拟浏览器,输入一个网址,从该网址获取到资源或内容 一、入门程序 #使用urlopen来进行爬取 from urllib.request import urlopen url "http://www.ba…...
我与C语言二周目邂逅vlog——6.文件操作
1. 为什么使⽤⽂件? 如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失 了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久…...
Hugo 部署与自动更新(Git)
文章目录 Nginx部署Hugonginx.confhugo.conf Hugo自动更新Hugo自动更新流程添加访问令牌添加web hookrust实现自动更新接口 Nginx部署Hugo nginx.conf user nginx; worker_processes auto;error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;even…...
HTTP代理揭秘:这些场景你都用对了吗?
HTTP代理是网络中常见的一种工具,可以帮助我们提升网络安全性和隐私保护,优化网络访问速度。本文将详细介绍什么是HTTP代理及其适用的场景。 HTTP代理是介于客户端(如浏览器)和服务器之间的中间服务器。它接收客户端的HTTP请求&a…...
电动汽车充电技术及运营知识问答pdf
电动汽车充电技术及运营知识问答 作者:马银山编著 出版社:北京:中国电力出版社 ISBN:9787512320406 资源大小:16.99MB 目录: http://literalink.top/resource/detail/7181601144102195200 第一章 电动汽车基本知识 1 1-1什么是电动汽车? 11-…...
playbooks 分布式部署 LNMP
1、环境配置 ansible 服务器 192.168.10.10nginx 服务器 192.168.10.20mysql 服务器 192.168.10.21php 服务器 192.168.10.22 2、安装 ansble #192.168.10.10节点 yum install -y epel-release #先安装 epel 源 yum install -y ansible配置主机清单 …...
成为git砖家(8): 使用 git log 查询范围内的 commit
文章目录 1. 查询 git log 的文档2. 不带任何参数: git log 啥意思?3. git log 最主要功能是什么?4. git log <commit1>..<commit2> 什么意思5. 查看最近n次commit6. References 1. 查询 git log 的文档 git help log --web市面上针对 git …...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
STM32标准库-ADC数模转换器
文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”:输入模块(GPIO、温度、V_REFINT)1.4.2 信号 “调度站”:多路开关1.4.3 信号 “加工厂”:ADC 转换器(规则组 注入…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...
高分辨率图像合成归一化流扩展
大家读完觉得有帮助记得关注和点赞!!! 1 摘要 我们提出了STARFlow,一种基于归一化流的可扩展生成模型,它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流(TARFlow&am…...
DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...
Qwen系列之Qwen3解读:最强开源模型的细节拆解
文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...
算法刷题-回溯
今天给大家分享的还是一道关于dfs回溯的问题,对于这类问题大家还是要多刷和总结,总体难度还是偏大。 对于回溯问题有几个关键点: 1.首先对于这类回溯可以节点可以随机选择的问题,要做mian函数中循环调用dfs(i&#x…...
