当前位置: 首页 > 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 …...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...