【go从零单排】gin+gorm理解及实现CRUD

🌈Don't worry , just coding!
内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。

📗概念

GIN

Gin 是一个高性能的 Go 语言 Web 框架,专为构建 RESTful API 和 Web 应用而设计。它以简洁的 API 和高效的性能著称,适合用于构建快速、可扩展的 Web 服务。Gin 基于 net/http 包构建,提供了许多功能,如中间件支持、路由分组、JSON 验证、错误处理等。

GORM

GORM 是一个流行的 Go 语言 ORM(对象关系映射)库,它提供了一个简单且强大的方式来与数据库进行交互。GORM 支持多种数据库,如 MySQL、PostgreSQL、SQLite 和 SQL Server。它允许开发者使用 Go 语言的结构体来表示数据库表,并通过方法调用来执行 CRUD(创建、读取、更新、删除)操作。

下载

官网下载

国内下载

💻代码

go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"net/http"
)

// 定义用户模型
// User 结构体表示用户模型,包含 ID、Name 和 Email 字段。
type User struct {
	ID    uint   `json:"id" gorm:"primaryKey"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

// 初始化数据库
func setupDatabase() *gorm.DB {
	db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}
	db.AutoMigrate(&User{}) // 自动迁移
	return db
}

// 创建用户
func createUser(c *gin.Context) { //参数:c *gin.Context 是 Gin 框架提供的上下文对象,包含请求和响应的相关信息。
	//数据库初始化:调用 setupDatabase() 函数,连接到 SQLite 数据库并返回数据库实例 db。
	db := setupDatabase()
	//定义变量:创建一个 User 类型的变量 user,用于存储从请求中绑定的数据。
	var user User
	//c.ShouldBindJSON(&user):尝试将请求体中的 JSON 数据绑定到 user 变量。
	//如果请求体不符合预期格式,ShouldBindJSON 将返回错误。
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	//创建记录:使用 GORM 的 Create 方法将 user 变量中的数据插入到数据库中。
	db.Create(&user)
	//成功响应:如果用户创建成功,返回 HTTP 状态码 200 OK 和新创建的用户数据(包括自动生成的 ID 等信息)。
	c.JSON(http.StatusOK, user)
}

// 获取所有用户
// c *gin.Context 是 Gin 框架提供的上下文对象,包含请求和响应的相关信息。
func getUsers(c *gin.Context) {
	db := setupDatabase()
	//创建一个切片 users,类型为 User,用于存储从数据库中查询到的用户记录。
	var users []User
	//使用 GORM 的 Find 方法查询所有用户记录,并将结果存储到 users 切片中。Find 方法会自动填充切片中的数据。
	db.Find(&users)
	//如果查询成功,返回 HTTP 状态码 200 OK 和查询到的用户数据(users 切片)
	c.JSON(http.StatusOK, users)
}

// 根据 ID 查询用户
func getUserByID(c *gin.Context) {
	db := setupDatabase()
	//从 URL 路径中获取用户的 ID。假设你的路由是 /users/:id,c.Param("id") 将提取该 ID。
	id := c.Param("id") // 从 URL 路径中获取用户 ID

	var user User
	//使用 GORM 的 First 方法根据 ID 查询用户。如果用户存在,user 变量将被填充;如果找不到,err 将不为 nil。
	if err := db.First(&user, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "用户未找到"})
		return
	}

	c.JSON(http.StatusOK, user) // 返回用户信息
}

// 更新用户
// updateUser,用于处理更新用户信息的请求。
// updateUser,用于处理更新用户信息的请求。
func updateUser(c *gin.Context) {
	db := setupDatabase()
	var user User
	//c.ShouldBindJSON(&user):尝试将请求体中的 JSON 数据绑定到 user 变量。
	//如果请求体不符合预期格式,ShouldBindJSON 将返回错误。
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	//使用 GORM 的 Where 方法找到 ID 为 user.ID 的记录,并使用 Updates 方法更新该用户的所有字段。
	if err := db.Where("id = ?", user.ID).Updates(user).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新失败: " + err.Error()})
		return
	}
	c.JSON(http.StatusOK, user)
}

// 更新用户的 email 字段为空
func updateEmail(c *gin.Context) {
	db := setupDatabase()
	id := c.Param("id") // 从 URL 中获取用户 ID
	DefaultEmail := "www.example.com"
	// 创建一个更新结构体,只包含需要更新的字段
	updateData := struct {
		Email *string `json:"email"` // 使用指针类型,可以设置为 nil
	}{
		Email: &DefaultEmail, // 设置 email 为 DefaultEmail
	}

	// 执行更新操作
	if err := db.Model(&User{}).Where("id = ?", id).Updates(updateData).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "用户 email 已设置为指定Email"})
}

// 删除用户
func deleteUser(c *gin.Context) {
	db := setupDatabase()
	id := c.Param("id")
	//&User{}:这里传入的是一个 User 结构体的指针。GORM 需要知道要删除哪个模型的记录。
	//id:这是要删除的记录的主键(通常是用户的 ID)。GORM 会根据这个 ID 找到对应的记录并进行删除。
	if err := db.Delete(&User{}, id).Error; err != nil {
		//如果 db.Delete(...) 返回了一个错误(即 err 不为 nil),则进入 if 语句块,通常会处理错误情况,比如返回一个 JSON 响应给客户端,表示删除失败。
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除失败: " + err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "用户已删除"})
}

func main() {
	r := gin.Default()

	// 定义路由
	r.POST("/users", createUser)       // 创建用户
	r.GET("/users", getUsers)          // 获取所有用户
	r.PUT("/users", updateUser)        // 更新用户
	r.DELETE("/users/:id", deleteUser) // 删除用户
	r.GET("/users/:id", getUserByID)   //根据ID查询用户
	r.PUT("/users/:id", updateEmail)   //根据ID跟新用户指定字段
	// 启动服务器
	r.Run(":9080")
}

🔍理解

GROM

准备工作

  • 初始化数据库连接
go 复制代码
package main

import (
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
    "log"
)

func setupDatabase() *gorm.DB {
    db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    if err != nil {
        log.Fatal("failed to connect to the database:", err)
    }
    return db
}
  • 定义模型
go 复制代码
type User struct {
    ID    uint   `gorm:"primaryKey"`
    Name  string `gorm:"size:100"`
    Email string `gorm:"uniqueIndex"`
}
  • 使用 GORM 的自动迁移功能创建表
c 复制代码
func migrate(db *gorm.DB) {
    db.AutoMigrate(&User{})
}

CRUD 操作示例

  • 创建记录:
c 复制代码
func createUser(db *gorm.DB, name string, email string) {
    user := User{Name: name, Email: email}
    db.Create(&user)
}
读取记录:
复制
func getUser(db *gorm.DB, id uint) User {
    var user User
    db.First(&user, id) // 根据 ID 查找用户
    return user
}
  • 更新记录:
c 复制代码
func updateUserEmail(db *gorm.DB, id uint, newEmail string) {
    var user User
    db.First(&user, id) // 查找用户
    user.Email = newEmail
    db.Save(&user) // 保存更新
}
  • 删除记录:
c 复制代码
func deleteUser(db *gorm.DB, id uint) {
    db.Delete(&User{}, id) // 根据 ID 删除用户
}
  • 事务示例
c 复制代码
func performTransaction(db *gorm.DB) {
    tx := db.Begin()
    defer func() {
        if r := recover(); r != nil {
            tx.Rollback() // 回滚事务
        }
    }()

    // 执行操作
    if err := tx.Create(&User{Name: "John", Email: "john@example.com"}).Error; err != nil {
        tx.Rollback()
        return
    }

    tx.Commit() // 提交事务
}

GIN

  1. 安装 Gin
c 复制代码
go get -u github.com/gin-gonic/gin
  1. 创建基本的 Gin 应用
c 复制代码
package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    // 创建一个默认的 Gin 路由引擎
    r := gin.Default()

    // 定义一个简单的 GET 路由
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "Hello, World!",
        })
    })

    // 启动服务
    r.Run(":8080") // 在 8080 端口启动服务
}
  1. 路由示例
  • 定义多个路由:
c 复制代码
r.GET("/users", getUsers)
r.POST("/users", createUser)
r.PUT("/users/:id", updateUser)
r.DELETE("/users/:id", deleteUser)
  • 路由处理函数:
c 复制代码
func getUsers(c *gin.Context) {
    // 处理获取用户的逻辑
}

func createUser(c *gin.Context) {
    // 处理创建用户的逻辑
}

func updateUser(c *gin.Context) {
    id := c.Param("id")
    // 处理更新用户的逻辑
}

func deleteUser(c *gin.Context) {
    id := c.Param("id")
    // 处理删除用户的逻辑
}
  1. 使用中间件
    Gin 支持中间件,可以在请求处理前后执行特定的逻辑。
c 复制代码
func Logger() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 处理请求前的逻辑
        log.Println("Request received")

        c.Next() // 调用下一个中间件或处理函数

        // 处理请求后的逻辑
        log.Println("Request completed")
    }
}


// 在路由组中使用中间件
r.Use(Logger())
  1. JSON 处理
c 复制代码
func createUser(c *gin.Context) {
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    // 处理用户创建逻辑
    c.JSON(201, user)
}
  1. 错误处理
    Gin 提供的错误处理机制:
c 复制代码
func getUser(c *gin.Context) {
    id := c.Param("id")
    user, err := findUserByID(id)
    if err != nil {
        c.JSON(404, gin.H{"error": "User not found"})
        return
    }
    c.JSON(200, user)
}

sqlite

  • SQLite 是一个轻量级的数据库,很多 Go 语言的 ORM(如 GORM)已经将 SQLite 的驱动程序包含在内。
  • SQLite 文件:当你在代码中指定数据库文件名(如 test.db)时,SQLite 会自动创建该文件。因此,你只需确保你的应用程序有权限在指定目录中创建文件。
  • 无需单独安装 SQLite,只需确保在你的 Go 项目中安装 GORM 和 SQLite 驱动即可。

💡 Tips

Gin 是一个高性能的 Go 语言 Web 框架,具有以下特点:

  • 高性能:Gin 使用了 httprouter,具有极快的路由速度。
  • 易用性:提供了简单易用的 API,方便开发者快速上手。
  • 中间件支持:可以轻松添加中间件,支持日志、认证等功能。
  • JSON 验证:内置 JSON 验证功能,简化请求参数的处理。
  • 丰富的文档:提供详细的文档和示例,帮助开发者理解和使用。

💪无人扶我青云志,我自踏雪至山巅。

相关推荐
Scott9999HH5 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社6 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海6 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖7 小时前
JDK 26 新特性详解
java·开发语言
马优晨7 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区9 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大10 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai10 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜10 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa10 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio