概述
如果您没有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_mcrud
import (
"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 string
if 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=v
for 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.Stmt
stmt, err = db.Prepare(sqlStr)
if err != nil {
fmt.Println(err)
return
}
defer stmt.Close()
// 执行查询
var rows *sql.Rows
rows, 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 main
import (
"database/sql"
"fmt"
"github.com/zhangdapeng520/zdpgo_mcrud"
_ "github.com/zhangdapeng520/zdpgo_mysql"
)
var (
db *sql.DB
err 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 main
import (
"database/sql"
"fmt"
"github.com/zhangdapeng520/zdpgo_httprouter"
_ "github.com/zhangdapeng520/zdpgo_mysql"
"net/http"
"time"
)
var (
db *sql.DB
err 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 []User
sqlStr := "select id,name,age from user"
var stmt *sql.Stmt
stmt, err = db.Prepare(sqlStr)
if err != nil {
fmt.Println(err)
return users
}
defer stmt.Close()
var rows *sql.Rows
rows, err = stmt.Query()
defer rows.Close()
// 读取
for rows.Next() {
var (
uid int64
name string
age 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 []User
sqlStr := "select id,name,age from user where id=?"
var stmt *sql.Stmt
stmt, err = db.Prepare(sqlStr)
if err != nil {
fmt.Println(err)
return users
}
defer stmt.Close()
var rows *sql.Rows
rows, err = stmt.Query(uid)
defer rows.Close()
// 读取
for rows.Next() {
var (
uid int64
name string
age 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.Stmt
stmt, err = db.Prepare(sqlStr)
if err != nil {
fmt.Println(err)
return -1
}
defer stmt.Close()
var result sql.Result
result, err = stmt.Exec(name, age)
if err != nil {
fmt.Println(err)
return -1
}
var uid int64
uid, 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.Result
result, err = db.Exec(sqlStr, name, age, id)
if err != nil {
fmt.Println(err)
return 0
}
var rowNum int64
rowNum, 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.Result
result, err = db.Exec(sqlStr, id)
if err != nil {
fmt.Println(err)
return 0
}
var rowNum int64
rowNum, 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 User
if len(users) > 0 {
user = users[0]
}
zdpgo_httprouter.ResponseSuccess(w, &user)
}
func RouterAddUser(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {
var user User
zdpgo_httprouter.GetJson(r, &user)
uid := DbAddUser(user.Name, user.Age)
user.Id = uid
zdpgo_httprouter.ResponseSuccess(w, &user)
}
func RouterUpdateUser(w http.ResponseWriter, r *http.Request, ps zdpgo_httprouter.Params) {
var user User
zdpgo_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 main
import (
"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.Body
bodyBytes, 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,return,nil,err,fmt,20240729,user,基础教程,Println From: https://blog.csdn.net/qq_37703224/article/details/140782954