go gin学习记录4
Posted 梁吉林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go gin学习记录4相关的知识,希望对你有一定的参考价值。
环境
环境:mac m1,go version 1.17.2, goland, mysql
除了原生sql,和orm操作之外,go还有一类包,只用于生成sql,典型的如sqlbuilder,今天就来研究一下它。
安装sqlbuilder
首先需要安装:
$ go get github.com/huandu/go-sqlbuilder
go: downloading github.com/huandu/go-sqlbuilder v1.19.0
go get: added github.com/huandu/go-sqlbuilder v1.19.0
go get: added github.com/huandu/xstrings v1.3.2
测试准备
为了实验,需要准备一个测试数据表,这里就按照第一节的user来复制一个worker表出来:
mysql> create table worker like user;
Query OK, 0 rows affected (0.02 sec)
接下来就到了创建controller和router group的节点了,第二节和第三节已经做了两遍,这里就直接贴代码了。
main.go:
worker := r.Group("/worker")
workerCtrl := controller.WorkerController
worker.POST("/createWorker", workerCtrl.CreateWorker)
worker.GET("/getWorkerInfo", workerCtrl.GetWorkerInfo)
worker.POST("/updateWorkerInfo", workerCtrl.UpdateWorkerInfo)
controller/worker.go:
package controller
import (
"github.com/gin-gonic/gin"
)
type WorkerController struct
ID int `json:"id"`
Name string `json:"name"`
Birth string `json:"birth"`
func (w *WorkerController) CreateWorker(c *gin.Context)
func (w *WorkerController) GetWorkerInfo(c *gin.Context)
func (w *WorkerController) UpdateWorkerInfo(c *gin.Context)
好的,前面这些重复的流程都搞定了。
sqlbuilder-插入操作
接下来我们开始完善代码,同样先从插入操作开始完善。
func (w *WorkerController) CreateWorker(c *gin.Context)
name := c.PostForm("name")
birth := c.PostForm("birth")
sb := sqlbuilder.NewInsertBuilder()
sb.InsertInto("worker")
sb.Cols("name", "birth")
sb.Values(name, birth)
sqlString, args := sb.Build()
log.Println(sqlString, args)
db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/t_gin?charset=utf8&parseTime=true")
if err != nil
log.Panic(err.Error())
_, err = db.Exec(sqlString, args)
if err != nil
log.Panic(err.Error())
c.JSON(http.StatusOK, gin.H
"code": 0,
"data": true,
)
运行一下看看
出错了。
好吧,看看是什么问题。
查一下terminal,能够看到打印出来的sql语句,已经一条错误信息:
2023/02/20 16:53:36 INSERT INTO worker (name, birth) VALUES (?, ?) [tata 2008-1-1]
2023/02/20 16:53:36 sql: converting argument $1 type: unsupported type []interface , a slice of interface
定位一下错误,发现是exec操作给的参数有点问题,因为Exec操作接收的参数是这样的:
func (db *DB) Exec(query string, args ...interface) (Result, error)
return db.ExecContext(context.Background(), query, args...)
我们调整一下代码:
_, err = db.Exec(sqlString, args...)
重新运行项目,这次是成功了
看一下数据库,数据正确插入了
mysql> select * from worker;
+----+------+----------+
| id | name | birth |
+----+------+----------+
| 2 | tata | 2008-1-1 |
+----+------+----------+
1 row in set (0.00 sec)
sqlbuilder-查询操作
好的,接下来再完善查询操作。
func (w *WorkerController) GetWorkerInfo(c *gin.Context)
id := c.Query("id")
sb := sqlbuilder.NewSelectBuilder()
sb.From("worker")
sb.Select("name,birth")
sb.Where(sb.Equal("id", id))
sqlString, args := sb.Build()
log.Println(sqlString, args)
db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/t_gin?charset=utf8&parseTime=true")
if err != nil
log.Panic(err.Error())
result := db.QueryRow(sqlString, args...)
var worker Worker
err = result.Scan(&worker.ID, &worker.Name, &worker.Birth)
if err != nil
log.Panic(err.Error())
c.JSON(http.StatusOK, gin.H
"code": 0,
"data": worker,
)
运行看看
又出错了
看下终端的输出:
2023/02/20 17:13:44 SELECT name,birth FROM worker WHERE id = ? [2]
2023/02/20 17:13:44 sql: expected 2 destination arguments in Scan, not 3
错误指向scan操作,说是只需要两个,却给了3个
检查代码后发现,是在生成sql时,select只查了name、birth两个字段,scan的时候却给了id、name、birth3个。
我们调整一下代码,将scan中的id去掉:
err = result.Scan(&worker.Name, &worker.Birth)
然后我们再运行:
好的,这次是成功的。
但是,有没有发现返回的数据是有问题的,id是0。
因为返回的是定义的struct,而查询时只查询了指定的字段,并没给id赋值,所以id字段用了一个默认值。
通过查询指定和结果绑定,就可以解决这个问题了。
sqlbuilder-更新操作
继续完善更新操作
func (w *WorkerController) UpdateWorkerInfo(c *gin.Context)
id := c.PostForm("id")
name := c.PostForm("name")
sb := sqlbuilder.NewUpdateBuilder()
sb.Update("worker")
sb.Where(sb.Equal("id", id))
sb.SetMore(sb.Assign("name", name))
sqlString, args := sb.Build()
log.Println(sqlString, args)
db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/t_gin?charset=utf8&parseTime=true")
if err != nil
log.Panic(err.Error())
_, err = db.Exec(sqlString, args...)
if err != nil
log.Panic(err.Error())
c.JSON(http.StatusOK, gin.H
"code": 0,
"data": true,
)
运行一下看看
运行成功了,我们看看数据表中的数据:
mysql> select * from worker;
+----+-----------+----------+
| id | name | birth |
+----+-----------+----------+
| 2 | this name | 2008-1-1 |
+----+-----------+----------+
1 row in set (0.03 sec)
也没有问题,符合预期。
然后呢?
sqlbuilder作为原生sql和orm之间的地带,适合什么样子的场景呢?我暂时还没有想到。
sqlbuilder比原生的多了一些复合操作,但它的功能就是用来生成SQL语句,具体的执行还是需要原生的db操作去执行。
而相比于gorm,它又显得过于简陋。当然好处是更浅显一些。
需求当中怎么选择,看个人的倾向吧。
今天就到这。
以上是关于go gin学习记录4的主要内容,如果未能解决你的问题,请参考以下文章