设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间03 现在时间03 缓存数据 希望你一辈子都是小孩儿 对所有事都好奇 爱哼小曲 永远快乐 喜欢和讨厌不用遮掩 每天都能跟喜欢的人讲一大堆废话 也能互道晚安❤️

希望你一辈子都是小孩儿 对所有事都好奇 爱哼小曲 永远快乐 喜欢和讨厌不用遮掩 每天都能跟喜欢的人讲一大堆废话 也能互道晚安❤️ -- 晚安

查看: 2070|回复: 5

Gin+Gorm实现CRUD的实战

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:224
  • 打卡月天数:0
  • 打卡总奖励:3517
  • 最近打卡:2025-06-30 06:53:44
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
418
主题
386
精华
0
金钱
4762
积分
854
注册时间
2023-1-8
最后登录
2025-6-30

发表于 2023-3-1 21:59:11 来自手机 | 显示全部楼层 |阅读模式
简介:

Q:Gin和Gorm都是干什么的?有什么区别?
A:Gin 和 Gorm 是 Go 编程语言中流行的开源库。但是,它们服务于不同的目的,通常在 web 开发项目中一起使用。
Gin 是一个用于构建 HTTP 服务器的 web 框架。它提供了一个简单易用的 API,用于处理 HTTP 请求和响应、路由、中间件和其他常见的 web 应用程序所需的功能。它以其高性能和简约为特点,提供了轻量级和灵活的解决方案来构建 web 服务器。
Gorm 是 Go 的一个 ORM(对象关系映射)库。它提供了一个简单易用的 API,用于与数据库交互、处理数据库迁移和执行常见的数据库操作,如查询、插入、更新和删除记录。它支持多种数据库后端,包括 MySQL、PostgreSQL、SQLite 等。
总而言之, Gin 是用于处理 HTTP 请求和响应、路由、中间件和其他与网络相关的东西的 web 框架,而 Gorm 则是用于与数据库交互并执行常见数据库操作的 ORM 库。它们通常一起使用,来处理 HTTP 请求/响应并在 web 开发项目中存储或获取数据。

开发环境:


  • Windows 10
  • VSCode

一、Gin


0. 快速入门:
  1. package main

  2. import (
  3.         "encoding/json"
  4.         "net/http"

  5.         "github.com/gin-gonic/gin"
  6.         "github.com/thinkerou/favicon"
  7. )

  8. // 中间件(拦截器),功能:预处理,登录授权、验证、分页、耗时统计...
  9. // func myHandler() gin.HandlerFunc {
  10. //         return func(ctx *gin.Context) {
  11. //                 // 通过自定义中间件,设置的值,在后续处理只要调用了这个中间件的都可以拿到这里的参数
  12. //                 ctx.Set("usersesion", "userid-1")
  13. //                 ctx.Next()  // 放行
  14. //                 ctx.Abort() // 阻止
  15. //         }
  16. // }

  17. func main() {
  18.         // 创建一个服务
  19.         ginServer := gin.Default()
  20.         ginServer.Use(favicon.New("./Arctime.ico")) // 这里如果添加了东西然后再运行没有变化,请重启浏览器,浏览器有缓存

  21.         // 加载静态页面
  22.         ginServer.LoadHTMLGlob("templates/*") // 一种是全局加载,一种是加载指定的文件

  23.         // 加载资源文件
  24.         ginServer.Static("/static", "./static")

  25.         // 相应一个页面给前端

  26.         ginServer.GET("/index", func(ctx *gin.Context) {
  27.                 ctx.HTML(http.StatusOK, "index.html", gin.H{
  28.                         "msg": "This data is come from Go background.",
  29.                 })
  30.         })

  31.         // 能加载静态页面也可以加载测试文件

  32.         // 获取请求中的参数

  33.         // 传统方式:usl?userid=xxx&username=conqueror712
  34.         // Rustful方式:/user/info/1/conqueror712

  35.         // 下面是传统方式的例子
  36.         ginServer.GET("/user/info", func(context *gin.Context) { // 这个格式是固定的
  37.                 userid := context.Query("userid")
  38.                 username := context.Query("username")
  39.                 // 拿到之后返回给前端
  40.                 context.JSON(http.StatusOK, gin.H{
  41.                         "userid":   userid,
  42.                         "username": username,
  43.                 })
  44.         })
  45.         // 此时执行代码之后,在浏览器中可以输入http://localhost:8081/user/info?userid=111&username=666
  46.         // 就可以看到返回了JSON格式的数据

  47.         // 下面是Rustful方式的例子
  48.         ginServer.GET("/user/info/:userid/:username", func(context *gin.Context) {
  49.                 userid := context.Param("userid")
  50.                 username := context.Param("username")
  51.                 // 还是一样,返回给前端
  52.                 context.JSON(http.StatusOK, gin.H{
  53.                         "userid":   userid,
  54.                         "username": username,
  55.                 })
  56.         })
  57.         // 指定代码后,只需要在浏览器中http://localhost:8081/user/info/111/555
  58.         // 就可以看到返回了JSON数据了,非常方便简洁

  59.         // 序列化
  60.         // 前端给后端传递JSON
  61.         ginServer.POST("/json", func(ctx *gin.Context) {
  62.                 // request.body
  63.                 data, _ := ctx.GetRawData()
  64.                 var m map[string]interface{} // Go语言中object一般用空接口来表示,可以接收anything
  65.                 // 顺带一提,1.18以上,interface可以直接改成any
  66.                 _ = json.Unmarshal(data, &m)
  67.                 ctx.JSON(http.StatusOK, m)
  68.         })
  69.         // 用apipost或者postman写一段json传到localhost:8081/json里就可以了
  70.         /*
  71.                 json示例:
  72.                 {
  73.                         "name": "Conqueror712",
  74.                         "age": 666,
  75.                         "address": "Mars"
  76.                 }
  77.         */
  78.         // 看到后端的实时响应里面接收到数据就可以了

  79.         // 处理表单请求 这些都是支持函数式编程,Go语言特性,可以把函数作为参数传进来
  80.         ginServer.POST("/user/add", func(ctx *gin.Context) {
  81.                 username := ctx.PostForm("username")
  82.                 password := ctx.PostForm("password")
  83.                 ctx.JSON(http.StatusOK, gin.H{
  84.                         "msg":      "ok",
  85.                         "username": username,
  86.                         "password": password,
  87.                 })
  88.         })

  89.         // 路由
  90.         ginServer.GET("/test", func(ctx *gin.Context) {
  91.                 // 重定向 -> 301
  92.                 ctx.Redirect(301, "https://conqueror712.gitee.io/conqueror712.gitee.io/")
  93.         })
  94.         // http://localhost:8081/test

  95.         // 404
  96.         ginServer.NoRoute(func(ctx *gin.Context) {
  97.                 ctx.HTML(404, "404.html", nil)
  98.         })

  99.         // 路由组暂略

  100.         // 服务器端口,用服务器端口来访问地址
  101.         ginServer.Run(":8081") // 不写的话默认是8080,也可以更改
  102. }
复制代码
API用法示例
  1. https://gin-gonic.com/zh-cn/docs/examples/
复制代码

1. 基准测试

Q:基准测试是什么?
A:基准测试,也称为性能测试或压力测试,是一种用于测量系统或组件性能的测试。基准测试的目的是了解系统或组件在特定条件下的性能,并将结果与其他类似系统或组件进行比较。基准测试可用于评估各种类型的系统和组件,包括硬件、软件、网络和整个系统。
Q:什么时候需要基准测试呀?
A:基准测试通常涉及在被测系统或组件上运行特定工作负载或任务,并测量吞吐量、延迟时间、CPU使用率、内存使用率等各种性能指标。基准测试的结果可用于识别瓶颈和性能问题,并做出有关如何优化系统或组件以提高性能的明智决策。
有许多不同类型的基准测试,每种类型都有自己的指标和工作负载。常见的基准测试类型包括:

  • 人工基准测试:使用人工工作负载来测量系统或组件的性能。
  • 真实世界基准测试:使用真实世界的工作负载或场景来测量系统或组件的性能。
  • 压力测试:旨在将系统或组件推到极限,以确定在正常使用条件下可能不明显的性能问题
重要的是要知道基准测试不是一次性的活动,而是应该定期进行的活动,以评估系统的性能并检测随时间的消耗。
Q:什么样的基准测试结果是我们想要的呀?
A:

  • 在一定的时间内实现的总调用数,越高越好
  • 单次操作耗时(ns/op),越低越好
  • 堆内存分配 (B/op), 越低越好
  • 每次操作的平均内存分配次数(allocs/op),越低越好

2. Gin的特性与Jsoniter:

Gin v1 稳定的特性:

  • 零分配路由。
  • 仍然是最快的 http 路由器和框架。
  • 完整的单元测试支持。
  • 实战考验。
  • API 冻结,新版本的发布不会破坏你的代码。
  • Gin 项目可以轻松部署在任何云提供商上。
Gin 使用 encoding/json 作为默认的 json 包,但是你可以在编译中使用标签将其修改为 jsoniter。
  1. $ go build -tags=jsoniter .
复制代码
Jsoniter是什么?

    1. json-iterator
    复制代码
    是一款快且灵活的
    1. JSON
    复制代码
    解析器,同时提供
    1. Java
    复制代码
    1. Go
    复制代码
    两个版本。
    1. json-iterator
    复制代码
    是最快的
    1. JSON
    复制代码
    解析器。它最多能比普通的解析器快10倍之多
  • 独特的
    1. iterator api
    复制代码
    能够直接遍历
    1. JSON
    复制代码
    ,极致性能、零内存分配
  • 从dsljson和jsonparser借鉴了大量代码。
下载依赖:
  1. go get github.com/json-iterator/go
复制代码

二、GORM


0. 特性与安装:


  • 全功能 ORM
  • 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)
  • Create,Save,Update,Delete,Find 中钩子方法
  • 支持
    1. Preload
    复制代码
    1. Joins
    复制代码
    的预加载
  • 事务,嵌套事务,Save Point,Rollback To Saved Point
  • Context、预编译模式、DryRun 模式
  • 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD
  • SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询
  • 复合主键,索引,约束
  • Auto Migration
  • 自定义 Logger
  • 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
  • 每个特性都经过了测试的重重考验
  • 开发者友好
  1. go get -u gorm.io/gorm
  2. go get -u gorm.io/driver/sqlite
复制代码
其他的补充内容:

  • Gorm是软删除,为了保证数据库的完整性

三、Navicat

新建连接 -> MySQL -> 连接名随便 -> 密码随便 -> 双击左侧打开 -> 右键information_schema -> 新建数据库 -> 名称crud-list -> 字符集utf8mb4
这里如果打开的时候报错
  1. navicat 1045 - access denied for user 'root'@'localhost' (using password: 'YES')
复制代码
,则需要查看自己的数据库本身的问题
四、Gin+Gorm的CRUD


连接数据库

编写测试代码,成功运行即可,但是这个时候还不能查看数据库是否被创建,
如果要看我们需要定义结构体,然后定义表迁移,具体代码如下:
  1. package main

  2. import (
  3.         "fmt"
  4.         "time"

  5.         // "gorm.io/driver/sqlite"
  6.         "github.com/gin-gonic/gin"
  7.         "gorm.io/driver/mysql"
  8.         "gorm.io/gorm"
  9. )

  10. func main() {
  11.         // 如何连接数据库 ? MySQL + Navicat
  12.         // 需要更改的内容:用户名,密码,数据库名称
  13.         dsn := "root:BqV?eGcc_1o+@tcp(127.0.0.1:3306)/crud-list?charset=utf8mb4&parseTime=True&loc=Local"
  14.         db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

  15.         fmt.Println("db = ", db)
  16.         fmt.Println("err = ", err)

  17.         // 连接池
  18.         sqlDB, err := db.DB()
  19.         // SetMaxIdleConns 设置空闲连接池中连接的最大数量
  20.         sqlDB.SetMaxIdleConns(10)
  21.         // SetMaxOpenConns 设置打开数据库连接的最大数量。
  22.         sqlDB.SetMaxOpenConns(100)
  23.         // SetConnMaxLifetime 设置了连接可复用的最大时间。
  24.         sqlDB.SetConnMaxLifetime(10 * time.Second) // 10秒钟

  25.         // 结构体
  26.         type List struct {
  27.                 Name    string
  28.                 State   string
  29.                 Phone   string
  30.                 Email   string
  31.                 Address string
  32.         }

  33.         // 迁移
  34.         db.AutoMigrate(&List{})

  35.         // 接口
  36.         r := gin.Default()

  37.         // 端口号
  38.         PORT := "3001"
  39.         r.Run(":" + PORT)
  40. }
复制代码
定义好之后我们运行,没有报错并且在终端显示出来3001就是正确的,这个时候我们可以去Navicat里面查看crud-list下面的"表",刷新后发现有一个lists产生,那就是对的了。
但是这个时候我们存在两个问题:

  • 没有主键:在struct里添加
    1. gorm.Model
    复制代码
    来解决,Ctrl+左键可以查看
    1. model
    复制代码
  • 表里面的名称变成了复数:详见文档的高级主题-GORM配置里,在
    1. *db*, *err* *:=* gorm.Open(mysql.Open(dsn), *&*gorm.Config{})
    复制代码
    里面添加一段话即可
更改完成之后我们要先在Navicat里面把原来的表
  1. lists
复制代码
删掉才能重新创建,这个时候我们重新运行,就会发现表单里面多了很多东西

结构体定义与优化

例如:
  1. `gorm:"type:varchar(20); not null" json:"name" binding:"required"`
复制代码
需要注意的是:

  • 结构体里面的变量(Name)必须首字母大写,否则创建不出列,会被自动忽略
  • gorm指定类型
  • json表示json接收的时候的名称
  • binding required表示必须传入

CRUD接口
  1. // 测试
  2. r.GET("/", func(c *gin.Context) {
  3.         c.JSON(200, gin.H{
  4.                 "message": "请求成功",
  5.         })
  6. })
复制代码
编写完这一段之后运行代码,然后去postman里面新建一个GET接口
  1. 127.0.0.1:3001
复制代码
然后send一下,出现请求成功就请求成功了。
增也是一样,写好之后直接用如下JSON来测试就可以:
  1. {
  2.         "name" : "张三",
  3.     "state" : "在职",
  4.     "phone" : "13900000000",
  5.     "email" : "6666@qq.com",
  6.     "address" : "二仙桥成华大道"
  7. }
复制代码
返回:
  1. {
  2.     "code": "200",
  3.     "data": {
  4.         "ID": 1,
  5.         "CreatedAt": "2023-01-24T09:27:36.73+08:00",
  6.         "UpdatedAt": "2023-01-24T09:27:36.73+08:00",
  7.         "DeletedAt": null,
  8.         "name": "张三",
  9.         "state": "在职",
  10.         "phone": "13900000000",
  11.         "email": "6666@qq.com",
  12.         "address": "二仙桥成华大道"
  13.     },
  14.     "msg": "添加成功"
  15. }
复制代码
这时候也可以在数据库里看到这条数据
删除也是一样,编写完运行之后添加一个DELETE接口,然后输入
  1. 127.0.0.1:3001/user/delete/2
复制代码
之后send就可以看到返回了(前提是有数据)
  1. {
  2.     "code": 200,
  3.     "msg": "删除成功"
  4. }
复制代码
如果是删除了不存在的id,就会返回
  1. {
  2.     "code": 400,
  3.     "msg": "id没有找到,删除失败"
  4. }
复制代码
顺带一提,事实上这个代码还可以优化,这里的if else太多了,后面优化的时候有错误直接return
修改也是一样,示例:
  1. {
  2.         "name" : "张三",
  3.     "state" : "离职",
  4.     "phone" : "13900000000",
  5.     "email" : "6666@qq.com",
  6.     "address" : "二仙桥成华大道"
  7. }
复制代码
返回:
  1. {
  2.     "code": 200,
  3.     "msg": "修改成功"
  4. }
复制代码
查询分为两种:

  • 条件查询
  • 分页查询
条件查询的话,直接写好了请求
  1. 127.0.0.1:3001/user/list/王五
复制代码
返回:
  1. {
  2.     "code": "200",
  3.     "data": [
  4.         {
  5.             "ID": 3,
  6.             "CreatedAt": "2023-01-24T10:06:25.305+08:00",
  7.             "UpdatedAt": "2023-01-24T10:06:25.305+08:00",
  8.             "DeletedAt": null,
  9.             "name": "王五",
  10.             "state": "在职",
  11.             "phone": "13100000000",
  12.             "email": "8888@qq.com",
  13.             "address": "八仙桥成华大道"
  14.         }
  15.     ],
  16.     "msg": "查询成功"
  17. }
复制代码
全部 / 分页查询的话
譬如说请求是:
  1. 127.0.0.1:3001/user/list?pageNum=1&pageSize=2
复制代码
意思就是查询第一页的两个
返回:
  1. {
  2.     "code": 200,
  3.     "data": {
  4.         "list": [
  5.             {
  6.                 "ID": 3,
  7.                 "CreatedAt": "2023-01-24T10:06:25.305+08:00",
  8.                 "UpdatedAt": "2023-01-24T10:06:25.305+08:00",
  9.                 "DeletedAt": null,
  10.                 "name": "王五",
  11.                 "state": "在职",
  12.                 "phone": "13100000000",
  13.                 "email": "8888@qq.com",
  14.                 "address": "八仙桥成华大道"
  15.             }
  16.         ],
  17.         "pageNum": 1,
  18.         "pageSize": 2,
  19.         "total": 2
  20.     },
  21.     "msg": "查询成功"
  22. }
复制代码
如果请求是:
  1. 127.0.0.1:3001/user/list
复制代码
返回:
  1. {
  2.     "code": 200,
  3.     "data": {
  4.         "list": [
  5.             {
  6.                 "ID": 1,
  7.                 "CreatedAt": "2023-01-24T09:27:36.73+08:00",
  8.                 "UpdatedAt": "2023-01-24T09:55:20.351+08:00",
  9.                 "DeletedAt": null,
  10.                 "name": "张三",
  11.                 "state": "离职",
  12.                 "phone": "13900000000",
  13.                 "email": "6666@qq.com",
  14.                 "address": "二仙桥成华大道"
  15.             },
  16.             {
  17.                 "ID": 3,
  18.                 "CreatedAt": "2023-01-24T10:06:25.305+08:00",
  19.                 "UpdatedAt": "2023-01-24T10:06:25.305+08:00",
  20.                 "DeletedAt": null,
  21.                 "name": "王五",
  22.                 "state": "在职",
  23.                 "phone": "13100000000",
  24.                 "email": "8888@qq.com",
  25.                 "address": "八仙桥成华大道"
  26.             }
  27.         ],
  28.         "pageNum": 0,
  29.         "pageSize": 0,
  30.         "total": 2
  31.     },
  32.     "msg": "查询成功"
  33. }
复制代码
完整代码如下:
  1. package main

  2. import (
  3.         "fmt"
  4.         "strconv"
  5.         "time"

  6.         // "gorm.io/driver/sqlite"
  7.         "github.com/gin-gonic/gin"
  8.         "gorm.io/driver/mysql"
  9.         "gorm.io/gorm"
  10.         "gorm.io/gorm/schema"
  11. )

  12. func main() {
  13.         // 如何连接数据库 ? MySQL + Navicat
  14.         // 需要更改的内容:用户名,密码,数据库名称
  15.         dsn := "root:password@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
  16.         db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
  17.                 NamingStrategy: schema.NamingStrategy{
  18.                         SingularTable: true,
  19.                 },
  20.         })

  21.         fmt.Println("db = ", db)
  22.         fmt.Println("err = ", err)

  23.         // 连接池
  24.         sqlDB, err := db.DB()
  25.         // SetMaxIdleConns 设置空闲连接池中连接的最大数量
  26.         sqlDB.SetMaxIdleConns(10)
  27.         // SetMaxOpenConns 设置打开数据库连接的最大数量。
  28.         sqlDB.SetMaxOpenConns(100)
  29.         // SetConnMaxLifetime 设置了连接可复用的最大时间。
  30.         sqlDB.SetConnMaxLifetime(10 * time.Second) // 10秒钟

  31.         // 结构体
  32.         type List struct {
  33.                 gorm.Model        // 主键
  34.                 Name       string `gorm:"type:varchar(20); not null" json:"name" binding:"required"`
  35.                 State      string `gorm:"type:varchar(20); not null" json:"state" binding:"required"`
  36.                 Phone      string `gorm:"type:varchar(20); not null" json:"phone" binding:"required"`
  37.                 Email      string `gorm:"type:varchar(40); not null" json:"email" binding:"required"`
  38.                 Address    string `gorm:"type:varchar(200); not null" json:"address" binding:"required"`
  39.         }

  40.         // 迁移
  41.         db.AutoMigrate(&List{})

  42.         // 接口
  43.         r := gin.Default()

  44.         // 测试
  45.         // r.GET("/", func(c *gin.Context) {
  46.         //         c.JSON(200, gin.H{
  47.         //                 "message": "请求成功",
  48.         //         })
  49.         // })

  50.         // 业务码约定:正确200,错误400

  51.         // 增
  52.         r.POST("/user/add", func(ctx *gin.Context) {
  53.                 // 定义一个变量指向结构体
  54.                 var data List
  55.                 // 绑定方法
  56.                 err := ctx.ShouldBindJSON(&data)
  57.                 // 判断绑定是否有错误
  58.                 if err != nil {
  59.                         ctx.JSON(200, gin.H{
  60.                                 "msg":  "添加失败",
  61.                                 "data": gin.H{},
  62.                                 "code": "400",
  63.                         })
  64.                 } else {
  65.                         // 数据库的操作
  66.                         db.Create(&data) // 创建一条数据
  67.                         ctx.JSON(200, gin.H{
  68.                                 "msg":  "添加成功",
  69.                                 "data": data,
  70.                                 "code": "200",
  71.                         })
  72.                 }
  73.         })

  74.         // 删
  75.         // 1. 找到对应的id对应的条目
  76.         // 2. 判断id是否存在
  77.         // 3. 从数据库中删除 or 返回id没有找到

  78.         // Restful编码规范
  79.         r.DELETE("/user/delete/:id", func(ctx *gin.Context) {
  80.                 var data []List
  81.                 // 接收id
  82.                 id := ctx.Param("id") // 如果有键值对形式的话用Query()
  83.                 // 判断id是否存在
  84.                 db.Where("id = ? ", id).Find(&data)
  85.                 if len(data) == 0 {
  86.                         ctx.JSON(200, gin.H{
  87.                                 "msg":  "id没有找到,删除失败",
  88.                                 "code": 400,
  89.                         })
  90.                 } else {
  91.                         // 操作数据库删除(删除id所对应的那一条)
  92.                         // db.Where("id = ? ", id).Delete(&data) <- 其实不需要这样写,因为查到的data里面就是要删除的数据
  93.                         db.Delete(&data)

  94.                         ctx.JSON(200, gin.H{
  95.                                 "msg":  "删除成功",
  96.                                 "code": 200,
  97.                         })
  98.                 }

  99.         })

  100.         // 改
  101.         r.PUT("/user/update/:id", func(ctx *gin.Context) {
  102.                 // 1. 找到对应的id所对应的条目
  103.                 // 2. 判断id是否存在
  104.                 // 3. 修改对应条目 or 返回id没有找到
  105.                 var data List
  106.                 id := ctx.Param("id")
  107.                 // db.Where("id = ?", id).Find(&data) 可以这样写,也可以写成下面那样
  108.                 // 还可以再Where后面加上Count函数,可以查出来这个条件对应的条数
  109.                 db.Select("id").Where("id = ? ", id).Find(&data)
  110.                 if data.ID == 0 {
  111.                         ctx.JSON(200, gin.H{
  112.                                 "msg":  "用户id没有找到",
  113.                                 "code": 400,
  114.                         })
  115.                 } else {
  116.                         // 绑定一下
  117.                         err := ctx.ShouldBindJSON(&data)
  118.                         if err != nil {
  119.                                 ctx.JSON(200, gin.H{
  120.                                         "msg":  "修改失败",
  121.                                         "code": 400,
  122.                                 })
  123.                         } else {
  124.                                 // db修改数据库内容
  125.                                 db.Where("id = ?", id).Updates(&data)
  126.                                 ctx.JSON(200, gin.H{
  127.                                         "msg":  "修改成功",
  128.                                         "code": 200,
  129.                                 })
  130.                         }
  131.                 }
  132.         })

  133.         // 查
  134.         // 第一种:条件查询,
  135.         r.GET("/user/list/:name", func(ctx *gin.Context) {
  136.                 // 获取路径参数
  137.                 name := ctx.Param("name")
  138.                 var dataList []List
  139.                 // 查询数据库
  140.                 db.Where("name = ? ", name).Find(&dataList)
  141.                 // 判断是否查询到数据
  142.                 if len(dataList) == 0 {
  143.                         ctx.JSON(200, gin.H{
  144.                                 "msg":  "没有查询到数据",
  145.                                 "code": "400",
  146.                                 "data": gin.H{},
  147.                         })
  148.                 } else {
  149.                         ctx.JSON(200, gin.H{
  150.                                 "msg":  "查询成功",
  151.                                 "code": "200",
  152.                                 "data": dataList,
  153.                         })
  154.                 }
  155.         })

  156.         // 第二种:全部查询 / 分页查询
  157.         r.GET("/user/list", func(ctx *gin.Context) {
  158.                 var dataList []List
  159.                 // 查询全部数据 or 查询分页数据
  160.                 pageSize, _ := strconv.Atoi(ctx.Query("pageSize"))
  161.                 pageNum, _ := strconv.Atoi(ctx.Query("pageNum"))

  162.                 // 判断是否需要分页
  163.                 if pageSize == 0 {
  164.                         pageSize = -1
  165.                 }
  166.                 if pageNum == 0 {
  167.                         pageNum = -1
  168.                 }

  169.                 offsetVal := (pageNum - 1) * pageSize // 固定写法 记住就行
  170.                 if pageNum == -1 && pageSize == -1 {
  171.                         offsetVal = -1
  172.                 }

  173.                 // 返回一个总数
  174.                 var total int64

  175.                 // 查询数据库
  176.                 db.Model(dataList).Count(&total).Limit(pageSize).Offset(offsetVal).Find(&dataList)

  177.                 if len(dataList) == 0 {
  178.                         ctx.JSON(200, gin.H{
  179.                                 "msg":  "没有查询到数据",
  180.                                 "code": 400,
  181.                                 "data": gin.H{},
  182.                         })
  183.                 } else {
  184.                         ctx.JSON(200, gin.H{
  185.                                 "msg":  "查询成功",
  186.                                 "code": 200,
  187.                                 "data": gin.H{
  188.                                         "list":     dataList,
  189.                                         "total":    total,
  190.                                         "pageNum":  pageNum,
  191.                                         "pageSize": pageSize,
  192.                                 },
  193.                         })
  194.                 }

  195.         })

  196.         // 端口号
  197.         PORT := "3001"
  198.         r.Run(":" + PORT)
  199. }
复制代码
到此这篇关于Gin+Gorm实战CRUD的文章就介绍到这了,更多相关Gin Gorm CRUD内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
15
积分
10
注册时间
2022-12-27
最后登录
2022-12-27

发表于 2023-10-31 09:15:15 | 显示全部楼层
感谢分享~~~~学习学习~~~~~
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
11
积分
2
注册时间
2023-5-3
最后登录
2023-5-3

发表于 2024-6-5 12:59:37 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
15
积分
10
注册时间
2022-12-25
最后登录
2022-12-25

发表于 2024-9-19 17:57:40 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
11
积分
2
注册时间
2024-9-11
最后登录
2024-9-11

发表于 2024-10-29 20:54:57 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
17
积分
14
注册时间
2022-12-24
最后登录
2022-12-24

发表于 2024-12-7 21:57:48 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼
4楼
5楼
6楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表