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私教~

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

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

相关文章

微信小游戏之 三消(一)

首先设定一下 单个 方块 cell 类&#xff1a; 类定义和属性 init 方法 用于初始化方块&#xff0c;接收游戏实例、数据、宽度、道具类型和位置。 onWarning 方法 设置警告精灵的帧&#xff0c;并播放闪烁动作&#xff0c;用于显示方块的警告状态。 grow 方法 根据传入的方向…

21.发布确认模式-高级

问题 生产环境中由于一些不明原因&#xff0c;导致rabbitmq重启&#xff0c;在重启的期间生产者消息投递失败&#xff0c;导致消息丢失&#xff0c;需要手动处理恢复。那么如何才能进行rabbitmq的消息可靠性投递&#xff1f;特别是在极端的情况&#xff0c;rabbitmq集群不可用…

文件操作相关的精讲

目录&#xff1a; 思维导图 一. 文件定义 二. 文件的打开和关闭 三. 文件的顺序读写操作 四. 文件的随机读写操作 五. 文本文件和二进制文件 六. 文件读取结束的判断 七.文件缓冲区 思维导图&#xff1a; 一. 文件定义 1.文件定义 C语言中&#xff0c;文件是指一组相…

Vue3可媲美Element Plus Tree组件实战之移除节点

Element Plus Tree自定义节点内容示例中介绍了移除节点的用法&#xff0c;个人觉得作为提供给用户API&#xff0c;应该遵循迪米特法则&#xff0c;把功能实现的细节封装在组件内部&#xff0c;而提供给用户最简单的操作方式&#xff0c;同时在此基础上支持用户的扩展。 因此&a…

接口测试支持IDEA插件一键同步API、新增思维导图快速评审测试用例,MeterSphere开源持续测试工具v3.1.0版本发布

2024年7月29日&#xff0c;MeterSphere开源持续测试工具正式发布v3.1.0版本。 在这一版本中&#xff0c;接口测试方面&#xff0c;支持通过IDEA插件一键同步API至MeterSphere&#xff1b;测试管理方面&#xff0c;“测试用例”模块新增通过思维导图模式快捷评审测试用例。在“…

挑战房市预测领头羊:KNN vs. 决策树 vs. 线性回归

挑战房市预测领头羊&#xff08;KNN&#xff0c;决策树&#xff0c;线性回归&#xff09; 1. 介绍1.1 K最近邻&#xff08;KNN&#xff09;&#xff1a;与邻居的友谊1.1.1 KNN的基础1.1.2 KNN的运作机制1.1.3 KNN的优缺点 1.2 决策树&#xff1a;解码房价的逻辑树1.2.1 决策树的…

CSS实现文本溢出处理

1.单行文本溢出 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wid…

总结——TI_音频信号分析仪

一、简介 设备&#xff1a;MSPM0G3507 库&#xff1a;CMSIS-DSP TI 数据分析&#xff1a;FFT 软件&#xff1a;CCS CLion MATLAB 目的&#xff1a;对音频信号进行采样&#xff08;滤波偏置处理&#xff09;&#xff0c;通过FFT获取信号的频率成分&am…

【Vue3】watchEffect

【Vue3】watchEffect 背景简介开发环境开发步骤及源码 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。本文…

了解Selenium中的WebElement

Selenium中到处都使用WebElement来执行各种操作。什么是WebElement&#xff1f;这篇文章将详细讨论WebElement。 Selenium中的WebElement是一个表示网站HTML元素的Java接口。HTML元素包含一个开始标记和一个结束标记&#xff0c;内容位于这两个标记之间。 HTML元素的重命名 …

C#插件 调用存储过程(输出参数类型)

存储过程 CREATE PROCEDURE [dbo].[GetSum]num1 INT,num2 INT,result INT OUTPUT AS BEGINselect result num1 num2 END C#代码 using Kingdee.BOS; using Kingdee.BOS.App.Data; using Kingdee.BOS.Core.Bill.PlugIn; using Kingdee.BOS.Util; using System; using System.…

放大电路总结

补充: 只有直流移动时才有Rbe动态等效电阻 从RsUs看进去,实际上不管接了什么东西都能够看成是一个Ri(输入电阻) Ri Ui/Ii Rb//Rbe Ui/Us Ri/(RiRs) Aus (Uo/Ui)*(Ui/Us) Au *Ri/(RiRs) 当前面是一个电压源的信号 我们就需要输入电阻更大 Ro--->输出电阻--->将…

基于FFmpeg和SDL的音视频解码播放的实现过程与相关细节

目录 1、视频播放器原理 2、FFMPEG解码 2.1 FFMPEG库 2.2、数据类型 2.3、解码 2.3.1、接口函数 2.3.2、解码流程 3、SDL播放 3.1、接口函数 3.2、视频播放 3.3、音频播放 4、音视频的同步 4.1、获取音频的播放时间戳 4.2、获取当前视频帧时间戳 4.3、获取视…

MongoDB教程(二十三):关于MongoDB自增机制

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、MongoD…

加密货币赋能跨境电商:PayPal供应链金融服务如何引领行业新趋势

跨境电商行业近年来呈现出爆发式增长&#xff0c;随着全球化贸易壁垒的降低和数字经济的快速发展&#xff0c;越来越多的商家和消费者跨越国界进行交易。根据eMarketer的数据&#xff0c;全球跨境电商交易额在2023年已超过4万亿美元&#xff0c;并预计在未来几年内仍将保持两位…

《Java初阶数据结构》----6.<优先级队列之PriorityQueue底层:堆>

前言 大家好&#xff0c;我目前在学习java。之前也学了一段时间&#xff0c;但是没有发布博客。时间过的真的很快。我会利用好这个暑假&#xff0c;来复习之前学过的内容&#xff0c;并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区…

ProxmoxPVE虚拟化平台--安装PVE虚拟机

Proxmox 虚拟机 Proxmox是一个基于Debian Linux和KVM的虚拟化平台&#xff0c;‌它提供了虚拟化的环境&#xff0c;‌允许用户在同一台物理机上运行多个虚拟机。‌Proxmox虚拟环境&#xff08;‌PVE&#xff09;‌是一个开源项目&#xff0c;‌由Proxmox Server Solutions Gmb…

重生之我当程序猿外包

第一章 个人介绍与收入历程 我出生于1999年&#xff0c;在大四下学期进入了一家互联网公司实习。当时的实习工资是3500元&#xff0c;公司还提供住宿。作为一名实习生&#xff0c;这个工资足够支付生活开销&#xff0c;每个月还能给父母转1000元&#xff0c;自己留2500元用来吃…

科普文:万字详解Kafka基本原理和应用

一、Kafka 简介 1. 消息引擎系统ABC Apache Kafka是一款开源的消息引擎系统&#xff0c;也是一个分布式流处理平台。除此之外&#xff0c;Kafka还能够被用作分布式存储系统&#xff08;极少&#xff09;。 A. 常见的两种消息引擎系统传输协议&#xff08;即用什么方式把消息…

探索 Milvus 存储系统:如何评估和优化 Milvus 存储性能

欢迎来到探索 Milvus 系列。Milvus 是一款支持水平扩展和具备出色性能的开源向量数据库。Milvus 的核心是其强大的存储系统&#xff0c;是数据持久化和存储的关键基础。该系统包括几个关键组成部分&#xff1a;元数据存储&#xff08;meta storage&#xff09;、消息存储&#…