Go语言入门32:Gin+GORM+MySQL完整实战(CRUD、连接池、事务、软删除、工程分层)

一、前言

前面31篇我们完成了 Go基础语法、并发、网络编程、Gin企业级高阶骨架

真实后端项目 99% 都是:接口 + 数据库CURD

本篇正式打通Gin + GORM + MySQL 完整链路,带你从零实现:

数据库连接、模型绑定、自动建表、增删改查、软删除、连接池配置、事务、简单工程分层。

所有代码复制即用、零报错、可直接用于项目开发

二、核心知识点预告

  • GORM 是什么:Go 最主流 ORM 框架,替代原生 SQL,开发效率极高

  • MySQL 连接 + 连接池参数调优(生产必备)

  • 结构体模型绑定数据表、自动迁移建表

  • 完整 RESTful CRUD 接口:新增、查询、修改、删除

  • 软删除实现(企业级标准,不真删数据)

  • GORM 事务操作(保证数据一致性)

  • 简易工程分层:模型层、数据库层、接口层

三、环境依赖安装

GORM v2 是目前稳定主流版本,搭配 MySQL 驱动

# 安装GORM核心库
go get gorm.io/gorm

# 安装MySQL驱动
go get gorm.io/driver/mysql

四、GORM连接MySQL(生产级连接池配置)

1. 连接参数说明

原生连接容易出现连接泄露、连接超时、并发卡死,必须配置连接池。

2. 完整数据库初始化代码

package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"log"
	"time"
)

// 全局DB变量,项目全局复用
var DB *gorm.DB

// InitDB 初始化MySQL连接 + 连接池配置
func InitDB() {
	// DSN格式:用户名:密码@tcp(127.0.0.1:3306)/数据库名?参数
	dsn := "root:123456@tcp(127.0.0.1:3306)/go_gin_demo?charset=utf8mb4&parseTime=True&loc=Local"

	// 打开连接
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		// 关闭默认日志,可开启查看SQL语句
		// Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		log.Fatal("数据库连接失败:", err)
	}

	// 获取原生SQL DB对象,配置连接池
	sqlDB, err := db.DB()
	if err != nil {
		log.Fatal("获取连接池失败:", err)
	}

	// 最大空闲连接数
	sqlDB.SetMaxIdleConns(10)
	// 最大打开连接数
	sqlDB.SetMaxOpenConns(100)
	// 连接最大存活时间
	sqlDB.SetConnMaxLifetime(1 * time.Hour)
	// 空闲连接超时时间
	sqlDB.SetConnMaxIdleTime(30 * time.Minute)

	DB = db
	log.Println("MySQL连接成功!")
}

func main() {
	// 初始化数据库
	InitDB()
}

五、定义数据模型 & 自动建表

GORM 最大优势:结构体即数据表,无需手写SQL建表,自动迁移字段。

1. 用户模型(含软删除、自动时间戳)

package main

import (
	"gorm.io/gorm"
	"time"
)

// User 用户模型
// gorm.Model 自带:ID、CreatedAt、UpdatedAt、DeletedAt
type User struct {
	gorm.Model
	Username string `gorm:"size:32;not null;comment:用户名"`
	Password string `gorm:"size:64;not null;comment:密码"`
	Age      int    `gorm:"default:18;comment:年龄"`
	Phone    string `gorm:"size:11;comment:手机号"`
}

// AutoMigrate 自动建表/更新表结构
func AutoMigrate() {
	err := DB.AutoMigrate(&User{})
	if err != nil {
		panic("表结构迁移失败:" + err.Error())
	}
}

func main() {
	InitDB()
	// 自动创建或更新数据表
	AutoMigrate()
}

运行后自动生成 users 数据表,自带主键、创建时间、更新时间、软删除标记。

六、Gin + GORM 完整CRUD接口实战

整合 Gin 路由 + GORM 数据库操作,实现企业级标准五套接口:新增、查询单条、查询列表、修改、删除

完整可运行CRUD代码

package main

import (
	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"log"
	"time"
)

var DB *gorm.DB

// User 用户模型
type User struct {
	gorm.Model
	Username string `gorm:"size:32;not null;comment:用户名"`
	Password string `gorm:"size:64;not null;comment:密码"`
	Age      int    `gorm:"default:18;comment:年龄"`
	Phone    string `gorm:"size:11;comment:手机号"`
}

// InitDB 初始化数据库
func InitDB() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/go_gin_demo?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatal("数据库连接失败:", err)
	}
	sqlDB, _ := db.DB()
	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetConnMaxLifetime(1 * time.Hour)
	DB = db
}

// AutoMigrate 自动建表
func AutoMigrate() {
	_ = DB.AutoMigrate(&User{})
}

func main() {
	// 初始化
	InitDB()
	AutoMigrate()

	r := gin.Default()

	// 1. 新增用户
	r.POST("/user/create", func(c *gin.Context) {
		var user User
		if err := c.ShouldBindJSON(&user); err != nil {
			c.JSON(400, gin.H{"code": 400, "msg": "参数错误"})
			return
		}
		// 数据库创建数据
		DB.Create(&user)
		c.JSON(200, gin.H{"code": 200, "msg": "创建成功", "data": user})
	})

	// 2. 根据ID查询单条用户
	r.GET("/user/get/:id", func(c *gin.Context) {
		id := c.Param("id")
		var user User
		DB.First(&user, id)
		c.JSON(200, gin.H{"code": 200, "data": user})
	})

	// 3. 查询用户列表
	r.GET("/user/list", func(c *gin.Context) {
		var list []User
		DB.Find(&list)
		c.JSON(200, gin.H{"code": 200, "data": list})
	})

	// 4. 更新用户信息
	r.POST("/user/update/:id", func(c *gin.Context) {
		id := c.Param("id")
		var user User
		// 先查询
		DB.First(&user, id)
		// 绑定新参数
		_ = c.ShouldBindJSON(&user)
		// 保存更新
		DB.Save(&user)
		c.JSON(200, gin.H{"code": 200, "msg": "更新成功", "data": user})
	})

	// 5. 删除用户(软删除)
	r.GET("/user/delete/:id", func(c *gin.Context) {
		id := c.Param("id")
		var user User
		DB.Delete(&user, id)
		c.JSON(200, gin.H{"code": 200, "msg": "删除成功(软删除)"})
	})

	_ = r.Run(":8080")
}

七、重点核心特性讲解

1. 软删除原理

模型内嵌gorm.Model 自带 DeletedAt 字段。

调用 DB.Delete()不会真正删除数据,只会给 DeletedAt 赋值时间戳。

普通查询 First/Find 会自动过滤已删除数据,企业项目标准用法。

2. 恢复已删除数据(了解)

// 恢复软删除数据
var user User
// Unscoped 查询包含已删除数据
DB.Unscoped().First(&user, id)
// 清空删除时间,恢复数据
DB.Model(&user).Update("deleted_at", nil)

3. 分页查询(高频业务)

// 分页:page页码,size每页条数
page := 1
size := 10
var list []User
var total int64

DB.Model(&User{}).Count(&total)
DB.Limit(size).Offset((page-1)*size).Find(&list)

八、GORM 事务实战(保证数据一致性)

涉及多表操作、连续写入、金额变动,必须使用事务,要么全部成功,要么全部回滚。

// TransactionDemo 事务示例
func TransactionDemo() error {
	return DB.Transaction(func(tx *gorm.DB) error {
		// 操作1:创建用户
		user := User{Username: "事务测试", Password: "123456"}
		tx.Create(&user)

		// 模拟异常,测试回滚
		// return errors.New("中断操作,事务回滚")

		// 返回nil则提交事务
		return nil
	})
}

返回 nil 自动提交,返回 error 自动回滚,极简安全。

九、简易工程分层规范(企业雏形)

单文件仅适合学习,项目开发必须分层,标准结构:

  • model:存放所有数据模型

  • db:数据库初始化、公共方法

  • controller:接收接口参数、响应数据

  • service:业务逻辑处理

  • router:路由注册

十、本篇总结

  • 掌握 GORM 连接 MySQL + 生产级连接池配置

  • 理解结构体映射数据表、自动迁移建表机制

  • 熟练使用 5 大基础 CURD 接口

  • 掌握企业级软删除特性

  • 掌握事务机制,解决数据一致性问题

  • 具备 Gin+MySQL 完整后端开发能力

十一、下期预告

下一篇:Go语言入门33:Gin分层架构实战(路由分层、控制器分层、服务层分层、解耦重构完整版),彻底告别单文件代码,搭建企业标准化项目架构!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容