当前位置: 首页 > news >正文

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的基础&#xff0c;应该学习如下前置课程。 Golang零基础入门Golang面向对象编程Go Web 基础Go语言开发REST API接口_20240728 基础不好的同学每节课的代码最好配合视频进行阅读和学习&#xff0c;如果基础比较扎实&#xff0c;则阅读本教程巩固一下相…...

相交链表 - 力扣(LeetCode)C语言

160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; (点击前面链接即可查看题目) 一、题目 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始…...

【Python】基础学习技能提升代码样例3:JSON文本处理

对json的处理&#xff0c;无非是编码和解码两部分 编码&#xff1a;将python数据结构转换为json字符串解码: 将json字符串转换为python数据结构 另外&#xff0c;还有.json文件的读写 一、编码 json.dumps(obj, *, skipkeysFalse, ensure_asciiTrue, check_circularTrue, a…...

最新Yiso智云搜索引擎系统源码/开源PHP源码/修复版

源码简介&#xff1a; 最新Yiso智云搜索引擎系统源码/开源PHP源码/修复版。Yiso 是一个性能非常好的搜索引擎&#xff0c;不仅免费开源&#xff0c;还能当作收录网址的平台来用呢&#xff01;只需要输入关键词&#xff0c;就能轻松找到相关的搜索结果内容。 1、Yiso 用的是自…...

Anconda 快速常用命令简洁版

目的&#xff1a;简单清楚的使用基本的conda 命令 可能需求 查看项目中的虚拟环境及依赖是否满足需求操作新环境来满足项目或者论文的实现 Anconda 常用命令 conda 查看基础命令1. 进入Anaconda 环境2. 查看版本3.查看有哪些虚拟环境4.激活虚拟环境5. 进入虚拟环境查看6. 退出…...

Android 系统启动动画

一、接着我们把 bootanimation.zip 动画文件 预制到 /system/media/ 目录下&#xff1a; 二、目录/system/media/bootanimation.zip PRODUCT_COPY_FILES \$(LOCAL_PATH)/bootanimation.zip:/system/media/bootanimation.zipPRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST \ /…...

解决antd打开modal时页面自动跳到顶部问题

问题原因&#xff1a;antd的样式中有一行&#xff0c;如下样式代码&#xff0c;这行代码导致了在本来有滚动条的页面底部触发modal弹出时&#xff0c;会自动滚动到页面顶部。 html {overflow-y: scroll; } 解决办法&#xff1a;删除这行代码、或者将html的overflow-y属性改成…...

什么是等保测评2.0,等保测评如何定级

在信息化时代&#xff0c;网络安全已成为国家安全的重要组成部分。为了应对日益复杂的网络安全形势&#xff0c;我国推出了网络安全等级保护制度&#xff0c;其中等保测评是评估信息系统安全防护能力的关键环节。本文将深入探讨等保2.0的测评流程和定级标准&#xff0c;以揭示其…...

【嵌入式英语教程--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 中的同步发送

在现代分布式系统中&#xff0c;消息队列是实现异步通信和解耦的重要组件。Apache RocketMQ 是一款高性能、高吞吐量的分布式消息中间件&#xff0c;广泛应用于电商、金融等领域。本文将详细介绍 RocketMQ 中的同步发送&#xff0c;包括其原理、应用场景、代码示例及注意事项。…...

c语言指针2

文章目录 一、void * 指针二、const关键字1.const修饰变量2.const修饰指针变量2. 1 const放在*的右边2. 2 const放在*的左边2. 3 总结 三、指针的运算3. 1指针的加减运算3. 2 指针 - 指针3. 3 指针的关系运算 四、野指针4. 1 什么叫野指针&#xff1f;4. 1 野指针的成因4.1.1 指…...

十七、openCV教程 图像轮廓

一、图像轮廓 图像轮廓是具有相同颜色或灰度的连续点的曲线.轮廓在形状分析和物体的检测和识别中很有用。 轮廓的作用:.用于图形分析、物体的识别和检测 注意点: 为了检测的准确性&#xff0c;需要先对图像进行二值化或Canny操作。 画轮廓时会修改输入的图像,如…...

基于视觉的语义匹配见多了,那基于雷达的呢?

论文题目&#xff1a; LiDAR-based HD Map Localization using Semantic Generalized ICP with Road Marking Detection 论文作者&#xff1a; Yansong Gong, Xinglian Zhang, Jingyi Feng, Xiao He and Dan Zhang 作者单位&#xff1a;北京驭势科技有限公司 导读&#xff…...

01、爬虫学习入门

爬虫&#xff1a;通过编写程序&#xff0c;来获取获取互联网上的资源 需求&#xff1a;用程序模拟浏览器&#xff0c;输入一个网址&#xff0c;从该网址获取到资源或内容 一、入门程序 #使用urlopen来进行爬取 from urllib.request import urlopen url "http://www.ba…...

我与C语言二周目邂逅vlog——6.文件操作

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失 了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久…...

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代理是网络中常见的一种工具&#xff0c;可以帮助我们提升网络安全性和隐私保护&#xff0c;优化网络访问速度。本文将详细介绍什么是HTTP代理及其适用的场景。 HTTP代理是介于客户端&#xff08;如浏览器&#xff09;和服务器之间的中间服务器。它接收客户端的HTTP请求&a…...

电动汽车充电技术及运营知识问答pdf

电动汽车充电技术及运营知识问答 作者:马银山编著 出版社:北京&#xff1a;中国电力出版社 ISBN:9787512320406 资源大小:16.99MB 目录&#xff1a; http://literalink.top/resource/detail/7181601144102195200 第一章 电动汽车基本知识 1 1-1什么是电动汽车&#xff1f; 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 啥意思&#xff1f;3. git log 最主要功能是什么&#xff1f;4. git log <commit1>..<commit2> 什么意思5. 查看最近n次commit6. References 1. 查询 git log 的文档 git help log --web市面上针对 git …...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…...

怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)

+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...