gin-gorm-mysql保姆级教程


前言

大概内容:

序言

主要内容概述如下:

  1. 项目初始化:首先着手创建一个新的Go项目,确保具备进行后续开发工作的基础框架。

  2. CRUD实现:在构建的Go项目中,使用gorm着手实现一组用于MySQL数据的crud操作。此阶段涵盖了创建(Create)、检索(Read)、更新(Update)与删除(Delete)功能的完整实现,确保每个接口均能准确对应相应的数据操作。

  3. CRUD接口实现:在构建的Go项目中,使用gin着手实现一组用于模拟数据操作的RESTful API接口。此阶段涵盖了创建(Create)、检索(Read)、更新(Update)与删除(Delete)功能的完整实现,确保每个接口均能准确对应相应的数据操作。

  4. 文档编制:最后,为已实现的接口集编写详尽的Swagger文档。利用Swagger的标准化描述格式,清晰阐述各个接口的路由、请求方法、请求参数、预期响应结构、HTTP状态码含义等关键信息,形成一套完整的API参考手册。此举旨在提升项目的技术透明度,方便团队内外的开发者查阅、理解和调用接口,促进代码的可维护性与协作效率。

操作系统:Windows 11。
开发环境:已配备Goland作为Go语言的主要集成开发环境(IDE)。
编程语言与框架:已预先安装Go编程语言(全称为Golang),这是实验所依赖的核心编程环境。在本次实验中,我们选用Go语言生态系统中的Gin框架作为主要的Web开发框架进行操作,以及gorm框架作为主要的数据库开发框架进行操作。选用的数据库为MySQL


提示:以下是本篇文章正文内容,下面案例仅供参考

新建项目

点击New Project
image.png
选择左侧栏的Go->填写Location->填写Environment->点击右下角的Create
其中绿色框起来的是你的项目所在的文件目录,红色框起来的是你的项目目录
蓝色框起来的是第三方代理:goproxy.cn,是一个在中国广泛使用的Go语言代理服务
GOPROXY=https://goproxy.cn,direct image.png
如图,你的项目已经创建成功了
image.png
在根目录下右键->new->Go File->填写main,然后回车即可

gorm连接数据库

安装 GORM 及 MySQL 驱动

确保已经安装了 GORM 库及其 MySQL 驱动。如果您尚未安装,可以使用以下命令进行安装:

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

image.png

连接MySQL数据库

完成安装后,您就可以在项目中导入并使用 Gorm 库来操作数据库了。
以下为根目录下新建文件main.go代码(以下代码属于测试连接MySQL是否成功):
dsn:包含数据库连接详细信息的 Data Source Name (DSN) 字符串。DSN 格式通常如下
user:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local

  • user: 数据库用户名。
  • password: 数据库密码。
  • localhost:3306: MySQL 服务器地址及端口。
  • dbname: 要连接的数据库名称。需要自行创建数据库才可以连接
  • charset=utf8mb4: 设置字符集为 UTF-8,支持多字节字符。
  • parseTime=True: 让驱动解析 MySQL 返回的 time.Time 类型。
  • loc=Local: 设置时区为本地时区。
import (
    "gorm.io/gorm"
    "gorm.io/driver/mysql" // 或其他数据库驱动
)

func main() {
    dsn := "user:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    _, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    // db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }
    // 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")
}

我的示例如下:
main.go

package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func main() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	_, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    // db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	// 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")
}

运行main.go文件,可以看到数据库连接成功image.png
到此,你已经连接上数据库了。接下来将main主函数内部的数据库连接代码迁移到main主函数外

初始化数据库连接

新建函数init,首先要说明的是:
在 Go 语言中,init 函数是一种特殊的函数,它在包的所有变量声明后自动执行,并且是在 main 函数执行之前运行的。每个包可以有多个 init 函数,这些函数按照它们在文件中出现的顺序依次执行。init 函数主要用于初始化操作,比如设置包级变量的初始值、检查或修复程序状态、注册、运行一次性计算等。
以下是 init 函数的几个关键特性:

  1. 自动执行:init 函数不需要在任何地方被显式调用,它会自动被 Go 运行时调用。
  2. 执行顺序:如果一个包导入了其他包,被导入包的 init 函数先于导入包执行。在同一个包中,如果有多个 init 函数(可以在同一个文件或不同文件中),它们按照它们在代码中出现的顺序执行。
  3. 无参数和返回值:init 函数没有参数也没有返回值。
  4. 多次定义:一个包可以包含多个 init 函数,甚至一个文件也可以包含多个 init 函数。
// 初始化数据库连接
func init() {}

将main主函数内这段代码迁移到函数init内部,并注释代码_, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}),去掉代码db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})的注释

    dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	// _, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	// 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")

定义全局变量DB

// 全局变量,用于存储数据库连接
var DB *gorm.DB

在init函数内部的最下方添加

DB = db

init完整代码如下

// 初始化数据库连接
func init() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	//_, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}
	// 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")
	DB = db
}

添加数据库日志

以下操作在init函数处修改
添加MySQL打印日志变量

    // mysql打印日志
	var mysqlLogger logger.Interface
	mysqlLogger = logger.Default.LogMode(logger.Info)

将变量mysqlLogger放入db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})&gorm.Config{}

Logger: mysqlLogger, // mysql打印日志

将连接失败的报错改为

log.Fatalf("Failed to connect to the database: %v", err)

设置dsn

init函数内部

    username := "root"
	password := "123456"
	host := "127.0.0.1"
	port := "3306"
	database := "test"

将dsn从dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"修改为

dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, database)

init完整代码如下

初始化数据库连接
func init() {
	username := "root"
	password := "123456"
	host := "127.0.0.1"
	port := "3306"
	database := "test"
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, database)

	// mysql打印日志
	var mysqlLogger logger.Interface
	mysqlLogger = logger.Default.LogMode(logger.Info)
	// _, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: mysqlLogger, // mysql打印日志
	})
	if err != nil {
		log.Fatalf("Failed to connect to the database: %v", err)
	}

	// 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")
	DB = db
}

定义user表

// 定义一个结构体来映射数据库中的表
type UserModel struct {
	// 使用 `comment:用户表主键` 设置字段的备注信息
	ID uint `gorm:"primaryKey"`
	// 使用 `type:varchar(20)` 设置字段类型及长度
	// 使用 `not null` 设置字段为非空
	// 使用 `comment:用户名` 设置字段的备注信息
	Name string `gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`
	// 使用 `size:10` 设置字段的长度
	// 使用 `comment:年龄` 设置字段的备注信息
	Age int `gorm:"column:age;size:10;comment:年龄;"`
}

// 将users表名更改为自定义表名sys_user
func (UserModel) TableName() string {
	return "sys_user"
}

main主函数内

// 示例:创建数据表(如果不存在)
DB.AutoMigrate(&UserModel{})

image.png
右键运行可以看到数据库连接成功
image.png
image.png
打开navicat可以看到,表已经成功创建
image.png
接下来主要写增加,所有查询,id查询,分页查询,id更新,id删除等6个关于用户的基本增删改查操作

create

main函数外

// 使用Gorm创建用户到数据库
func Create(user UserModel) {
    // 使用Gorm创建用户到数据库
    result := DB.Create(&user)
    if result.Error != nil {
        // 处理创建失败的错误
        log.Fatal(result.Error)
    }
    // 检查创建结果,受影响的行数(应为1)
    if result.RowsAffected == 1 {
        fmt.Println("User created successfully.")
    } else {
        fmt.Println("User creation failed.")
    }
}

main函数内部
以下为插入单条数据和多条数据的代码样例

    //创建用户数据
	userExample := UserModel{Name: "KiTy", Age: 30}
	// 使用Gorm创建用户到数据库
	Create(userExample)
	// 创建3个用户实例
	user1 := UserModel{Name: "John", Age: 30}
	user2 := UserModel{Name: "Mike", Age: 32}
	user3 := UserModel{Name: "Anna", Age: 20}
    // 创建用户实例数组
	users := []UserModel{user1, user2, user3}
    // 使用 for 循环遍历用户数据,并通过 Gorm 框架逐一将这些用户数据创建到数据库中。
    // 当然,也可以另外创建一个函数,将传参改为用户数据数组,然后使用该函数批量创建用户数据。请自行探索
	for _, user := range users {
		Create(user)
	}

read

main主函数外

// 使用Gorm在数据库中查询所有用户数据
func ListUser() {
	// 示例:查询所有用户数据
	var users []UserModel
	result := DB.Find(&users)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Fatal(result.Error)
	}
	// 检查查询结果,查询到的用户数量(应为大于0)
	if result.RowsAffected > 0 {
		fmt.Println("Users found:")
		for _, user := range users {
			fmt.Printf("ID: %d, Name: %s, Age: %d\n", user.ID, user.Name, user.Age)
		}
	} else {
		fmt.Println("No users found.")
	}
}

// 使用Gorm在数据库中利用用户ID查询单个用户数据
func GetUser(id int) {
	// 示例:查询单个用户数据
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Fatal(result.Error)
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		fmt.Printf("User found: ID: %d, Name: %s, Age: %d\n", user.ID, user.Name, user.Age)
	} else {
		fmt.Println("No user found with ID:", id)
	}
}

// 分页查询
func PaginateUser(page, pageSize int) {
	// 示例:分页查询用户数据
	var users []UserModel
	// 计算偏移量
	offset := (page - 1) * pageSize
	result := DB.Limit(pageSize).Offset(offset).Find(&users)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Fatal(result.Error)
	}
	// 检查查询结果,查询到的用户数量(应为大于0)
	if result.RowsAffected > 0 {
		fmt.Printf("Users found (page %d):\n", page)
		for _, user := range users {
			fmt.Printf("ID: %d, Name: %s, Age: %d\n", user.ID, user.Name, user.Age)
		}
	} else {
		fmt.Println("No users found.")
	}
}

main主函数内

    // 使用Gorm在数据库中查询所有用户数据
	ListUser()
	// 使用Gorm在数据库中利用用户ID查询单个用户数据
	GetUser(1)
	// 分页查询
	PaginateUser(1, 2)

update

main主函数外

// 使用Gorm在数据库中更新单个用户数据
func UpdateUser(id int, user UserModel) {
	// 示例:更新用户数据
	result := DB.Model(&user).Where("id = ?", id).Updates(user)
	if result.Error != nil {
		// 处理更新失败的错误
		log.Fatal(result.Error)
	}
	// 检查更新结果,受影响的行数(应为1)
	if result.RowsAffected == 1 {
		fmt.Println("User updated successfully.")
	} else {
		fmt.Println("User update failed.")
	}
}

main主函数内

    // 使用Gorm在数据库中更新单个用户数据
	userToUpdate := UserModel{ID: 1, Name: "Kitty", Age: 31}
	UpdateUser(1, userToUpdate)

delete

main主函数外

// 使用Gorm在数据库中删除单个用户数据
func DeleteUser(id int) {
	// 示例:删除用户数据
	result := DB.Delete(&UserModel{}, id)
	if result.Error != nil {
		// 处理删除失败的错误
		log.Fatal(result.Error)
	}
	// 检查删除结果,受影响的行数(应为1)
	if result.RowsAffected == 1 {
		fmt.Println("User deleted successfully.")
	} else {
		fmt.Println("User deletion failed.")
	}
}

main主函数内

    // 使用Gorm在数据库中删除单个用户数据
	DeleteUser(1)

源码

package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
)

// 全局变量,用于存储数据库连接
var DB *gorm.DB

// 定义一个结构体来映射数据库中的表
type UserModel struct {
	// 使用 `comment:用户表主键` 设置字段的备注信息
	ID uint `gorm:"primaryKey"`
	// 使用 `type:varchar(20)` 设置字段类型及长度
	// 使用 `not null` 设置字段为非空
	// 使用 `comment:用户名` 设置字段的备注信息
	Name string `gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`
	// 使用 `size:10` 设置字段的长度
	// 使用 `comment:年龄` 设置字段的备注信息
	Age int `gorm:"column:age;size:10;comment:年龄;"`
}

// 将users表名更改为自定义表名sys_user
func (UserModel) TableName() string {
	return "sys_user"
}

// 初始化数据库连接
func init() {
	username := "root"
	password := "123456"
	host := "127.0.0.1"
	port := "3306"
	database := "test"
	
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, database)
	
    // mysql打印日志
	var mysqlLogger logger.Interface
	mysqlLogger = logger.Default.LogMode(logger.Info)
    //_, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: mysqlLogger, // mysql打印日志
	})
	if err != nil {
		log.Fatalf("Failed to connect to the database: %v", err)
	}
	// 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")
	DB = db
}

// 使用Gorm在数据库中查询所有用户数据
func ListUser() {
	// 示例:查询所有用户数据
	var users []UserModel
	result := DB.Find(&users)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Fatal(result.Error)
	}
	// 检查查询结果,查询到的用户数量(应为大于0)
	if result.RowsAffected > 0 {
		fmt.Println("Users found:")
		for _, user := range users {
			fmt.Printf("ID: %d, Name: %s, Age: %d\n", user.ID, user.Name, user.Age)
		}
	} else {
		fmt.Println("No users found.")
	}
}

// 使用Gorm创建用户到数据库
func Create(user UserModel) {
	// 使用Gorm创建用户到数据库
	result := DB.Create(&user)
	if result.Error != nil {
		// 处理创建失败的错误
		log.Fatal(result.Error)
	}
	// 检查创建结果,受影响的行数(应为1)
	if result.RowsAffected == 1 {
		fmt.Println("User created successfully.")
	} else {
		fmt.Println("User creation failed.")
	}
}

// 使用Gorm在数据库中利用用户ID查询单个用户数据
func GetUser(id int) {
	// 示例:查询单个用户数据
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Fatal(result.Error)
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		fmt.Printf("User found: ID: %d, Name: %s, Age: %d\n", user.ID, user.Name, user.Age)
	} else {
		fmt.Println("No user found with ID:", id)
	}
}

// 分页查询
func PaginateUser(page, pageSize int) {
	// 示例:分页查询用户数据
	var users []UserModel
	// 计算偏移量
	offset := (page - 1) * pageSize
	result := DB.Limit(pageSize).Offset(offset).Find(&users)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Fatal(result.Error)
	}
	// 检查查询结果,查询到的用户数量(应为大于0)
	if result.RowsAffected > 0 {
		fmt.Printf("Users found (page %d):\n", page)
		for _, user := range users {
			fmt.Printf("ID: %d, Name: %s, Age: %d\n", user.ID, user.Name, user.Age)
		}
	} else {
		fmt.Println("No users found.")
	}
}

// 使用Gorm在数据库中更新单个用户数据
func UpdateUser(id int, user UserModel) {
	// 示例:更新用户数据
	result := DB.Model(&user).Where("id = ?", id).Updates(user)
	if result.Error != nil {
		// 处理更新失败的错误
		log.Fatal(result.Error)
	}
	// 检查更新结果,受影响的行数(应为1)
	if result.RowsAffected == 1 {
		fmt.Println("User updated successfully.")
	} else {
		fmt.Println("User update failed.")
	}
}

// 使用Gorm在数据库中删除单个用户数据
func DeleteUser(id int) {
	// 示例:删除用户数据
	result := DB.Delete(&UserModel{}, id)
	if result.Error != nil {
		// 处理删除失败的错误
		log.Fatal(result.Error)
	}
	// 检查删除结果,受影响的行数(应为1)
	if result.RowsAffected == 1 {
		fmt.Println("User deleted successfully.")
	} else {
		fmt.Println("User deletion failed.")
	}
}

func main() {
	// 示例:创建数据表(如果不存在)
	DB.AutoMigrate(&UserModel{})
	//创建用户数据
	userExample := UserModel{Name: "KiTy", Age: 30}
	// 使用Gorm创建用户到数据库
	Create(userExample)
	// 创建3个用户实例
	user1 := UserModel{Name: "John", Age: 30}
	user2 := UserModel{Name: "Mike", Age: 32}
	user3 := UserModel{Name: "Anna", Age: 20}
	// 创建用户实例数组
	users := []UserModel{user1, user2, user3}
	// 使用 for 循环遍历用户数据,并通过 Gorm 框架逐一将这些用户数据创建到数据库中。
	// 当然,也可以另外创建一个函数,将传参改为用户数据数组,然后使用该函数批量创建用户数据。请自行探索
	for _, user := range users {
		Create(user)
	}
	// 使用Gorm在数据库中查询所有用户数据
	ListUser()
	// 使用Gorm在数据库中利用用户ID查询单个用户数据
	GetUser(1)
	// 分页查询
	PaginateUser(1, 2)
	// 使用Gorm在数据库中更新单个用户数据
	userToUpdate := UserModel{Name: "Kitty", Age: 31}
	UpdateUser(1, userToUpdate)
	// 使用Gorm在数据库中删除单个用户数据
	DeleteUser(1)
}

右键运行,出现与下图类似的即为成功
image.png

gorm+gin+swagger

开始

确保已经安装了Gin框架和GORM 库及其MySQL 驱动。如果尚未安装,可以使用以下命令进行安装:

go get -u gorm.io/gorm # 安装GORM
go get -u gorm.io/driver/mysql # 安装MySQL 驱动
go get -u github.com/gin-gonic/gin # 安装Gin框架

注意:这里使用的是上面gorm连接数据库的源码,删减为以下代码,其中UserModel添加了json响应格式

package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
)

// 全局变量,用于存储数据库连接
var DB *gorm.DB

// 定义一个结构体来映射数据库中的表
type UserModel struct {
	// 使用 `comment:用户表主键` 设置字段的备注信息
	ID uint `json:"id" gorm:"primaryKey"`
	// 使用 `type:varchar(20)` 设置字段类型及长度
	// 使用 `not null` 设置字段为非空
	// 使用 `comment:用户名` 设置字段的备注信息
	Name string `json:"user_name" gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`
	// 使用 `size:10` 设置字段的长度
	// 使用 `comment:年龄` 设置字段的备注信息
	Age int `json:"age" gorm:"column:age;size:10;comment:年龄;"`
}

// 将users表名更改为自定义表名sys_user
func (UserModel) TableName() string {
	return "sys_user"
}

func init() {
	username := "root"
	password := "123456"
	host := "127.0.0.1"
	port := "3306"
	database := "test"
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, database)

	// mysql打印日志
	var mysqlLogger logger.Interface
	mysqlLogger = logger.Default.LogMode(logger.Info)
	// _, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: mysqlLogger, // mysql打印日志
	})
	if err != nil {
		log.Fatalf("Failed to connect to the database: %v", err)
	}

	// 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")
	DB = db
}

func main() {
    // 示例:创建数据表(如果不存在)
	DB.AutoMigrate(&UserModel{})
}

定义一个结构体来映射返回的数据

// 定义一个结构体来映射返回的数据
type Response struct {
	// 状态码
	Code int `json:"code"`
	// 数据
	Data interface{} `json:"data"`
	// 消息
	Msg string `json:"msg"`
}

定义分页查询的返回体格式

// 定义一个结构体来映射分页查询的数据
type Pagination struct {
    // 当前页码
    Page int `json:"page"`
    // 每页数量
    PageSize int `json:"pageSize"`
    // 总页数
    TotalPages int `json:"totalPages"`
    // 总记录数
    TotalCount int `json:"totalCount"`
}

// 定义一个结构体来映射查询用户列表的返回数据
type UserData struct {
    // 用户列表
    Users []UserModel `json:"users"`
    // 分页信息
    Pagination Pagination `json:"pagination"`
}

定义一个user用户的请求体,其中不包括id

type UserRequest struct {
	// 使用 `type:varchar(20)` 设置字段类型及长度
	// 使用 `not null` 设置字段为非空
	// 使用 `comment:用户名` 设置字段的备注信息
	Name string `json:"user_name" gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`
	// 使用 `size:10` 设置字段的长度
	// 使用 `comment:年龄` 设置字段的备注信息
	Age int `json:"age" gorm:"column:age;size:10;comment:年龄;"`
}

添加路由

给main主函数添加路由,以下为main函数完整代码
其中分页查询功能和查询所有用户功能均在userGroup.GET("/", listUser)内部实现

func main() {
    DB.AutoMigrate(&UserModel{})
	// 创建gin路由
	router := gin.Default()

	// 定义user的路由分组
	userGroup := router.Group("/users")
	{
        userGroup.GET("/", listUser)
		userGroup.POST("/", createUser)
		userGroup.GET("/:id", getUser)
		userGroup.PUT("/:id", updateUser)
		userGroup.DELETE("/:id", deleteUser)
	}

	// 启动HTTP服务器并监听在8080端口
	router.Run(":8080")
}

添加路由函数

func listUser(c *gin.Context) {
	// 从请求中获取page和pageSize参数,设置默认值
	pageStr, pageSizeStr := c.Query("page"), c.Query("pageSize")
	page, errPage := strconv.Atoi(pageStr)
	pageSize, errPageSize := strconv.Atoi(pageSizeStr)

	if errPage != nil || page < 1 {
		page = 1
	}
	if errPageSize != nil || pageSize < 1 {
		pageSize = 10
	}

	var users []UserModel
	var totalCount int64
	DB.Model(&UserModel{}).Count(&totalCount) // 计算总用户数

	totalPages := int((totalCount + int64(pageSize) - 1) / int64(pageSize)) // 计算总页数
	offset := (page - 1) * pageSize

	result := DB.Offset(offset).Limit(pageSize).Find(&users) // 分页查询用户

	if result.Error != nil {
		c.JSON(500, Response{Code: 500, Data: nil, Msg: "Database error"})
		return
	}

	// 构建分页信息
	pagination := Pagination{
		Page:       page,
		PageSize:   pageSize,
		TotalPages: totalPages,
		TotalCount: int(totalCount),
	}

	userData := UserData{
		Users:      users,
		Pagination: pagination,
	}

	// 添加分页信息到响应中
	c.JSON(200, Response{Code: 200, Data: userData, Msg: "Success"})
}

func createUser(c *gin.Context) {
	// 解析请求参数
	var user UserModel
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "Invalid request body"})
		return
	}
	// 创建用户
	result := DB.Create(&user)
	if result.Error != nil {
		// 处理创建失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User creation failed"})
	}
	// 检查创建结果,受影响的行数(应为1)
	if result.RowsAffected == 1 {
		// 返回创建成功的用户
		c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User created successfully"})
	} else {
		// 返回创建失败
		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User creation failed"})
	}
}

func getUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 返回用户
		c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User found"})
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

func updateUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 更新用户
		if err := c.ShouldBindJSON(&user); err != nil {
			c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "Invalid request body"})
			return
		}
		result = DB.Save(&user)
		if result.Error != nil {
			// 处理更新失败的错误
			log.Println(result.Error)
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User update failed"})
		}
		// 检查更新结果,受影响的行数(应为1)
		if result.RowsAffected == 1 {
			// 返回更新成功的用户
			c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User updated successfully"})
		} else {
			// 返回更新失败
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User update failed"})
		}
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

func deleteUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 删除用户
		result = DB.Delete(&user, id)
		if result.Error != nil {
			// 处理删除失败的错误
			log.Println(result.Error)
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User deletion failed"})
		}
		// 检查删除结果,受影响的行数(应为1)
		if result.RowsAffected == 1 {
			// 返回删除成功的用户
			c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User deleted successfully"})
		} else {
			// 返回删除失败
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User deletion failed"})
		}
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

完整代码

main.go完整

package main

import (
	"fmt"
	_ "gin-gorm-crud/docs"
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
	"net/http"
	"strconv"
)

// 全局变量,用于存储数据库连接
var DB *gorm.DB

// 定义一个结构体来映射数据库中的表
type UserModel struct {
	// 使用 `gorm:"column:id"` 设置字段名
	// 使用 `comment:用户表主键` 设置字段的备注信息
	ID uint `json:"id" gorm:"primaryKey"`
	// 使用 `type:varchar(20)` 设置字段类型及长度
	// 使用 `not null` 设置字段为非空
	// 使用 `comment:用户名` 设置字段的备注信息
	Name string `json:"user_name" gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`
	// 使用 `size:10` 设置字段的长度
	// 使用 `comment:年龄` 设置字段的备注信息
	Age int `json:"age" gorm:"column:age;size:10;comment:年龄;"`
}

type UserRequest struct {
	// 使用 `type:varchar(20)` 设置字段类型及长度
	// 使用 `not null` 设置字段为非空
	// 使用 `comment:用户名` 设置字段的备注信息
	Name string `json:"user_name" gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`
	// 使用 `size:10` 设置字段的长度
	// 使用 `comment:年龄` 设置字段的备注信息
	Age int `json:"age" gorm:"column:age;size:10;comment:年龄;"`
}

// 将users表名更改为自定义表名sys_user
func (UserModel) TableName() string {
	return "sys_user"
}

// 定义一个结构体来映射返回的数据
type Response struct {
	// 状态码
	Code int `json:"code"`
	// 数据
	Data interface{} `json:"data"`
	// 消息
	Msg string `json:"msg"`
}

// 定义一个结构体来映射分页查询的数据
type Pagination struct {
	// 当前页码
	Page int `json:"page"`
	// 每页数量
	PageSize int `json:"pageSize"`
	// 总页数
	TotalPages int `json:"totalPages"`
	// 总记录数
	TotalCount int `json:"totalCount"`
}

// 定义一个结构体来映射查询用户列表的返回数据
type UserData struct {
	// 用户列表
	Users []UserModel `json:"users"`
	// 分页信息
	Pagination Pagination `json:"pagination"`
}

func init() {
	username := "root"
	password := "123456"
	host := "127.0.0.1"
	port := "3306"
	database := "test"
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, database)

	// mysql打印日志
	var mysqlLogger logger.Interface
	mysqlLogger = logger.Default.LogMode(logger.Info)
	// _, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: mysqlLogger, // mysql打印日志
	})
	if err != nil {
		log.Fatalf("Failed to connect to the database: %v", err)
	}

	// 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")
	DB = db
}

func listUser(c *gin.Context) {
	// 从请求中获取page和pageSize参数,设置默认值
	pageStr, pageSizeStr := c.Query("page"), c.Query("pageSize")
	page, errPage := strconv.Atoi(pageStr)
	pageSize, errPageSize := strconv.Atoi(pageSizeStr)

	if errPage != nil || page < 1 {
		page = 1
	}
	if errPageSize != nil || pageSize < 1 {
		pageSize = 10
	}

	var users []UserModel
	var totalCount int64
	DB.Model(&UserModel{}).Count(&totalCount) // 计算总用户数

	totalPages := int((totalCount + int64(pageSize) - 1) / int64(pageSize)) // 计算总页数
	offset := (page - 1) * pageSize

	result := DB.Offset(offset).Limit(pageSize).Find(&users) // 分页查询用户

	if result.Error != nil {
		c.JSON(500, Response{Code: 500, Data: nil, Msg: "Database error"})
		return
	}

	// 构建分页信息
	pagination := Pagination{
		Page:       page,
		PageSize:   pageSize,
		TotalPages: totalPages,
		TotalCount: int(totalCount),
	}

	userData := UserData{
		Users:      users,
		Pagination: pagination,
	}

	// 添加分页信息到响应中
	c.JSON(200, Response{Code: 200, Data: userData, Msg: "Success"})
}

func createUser(c *gin.Context) {
	// 解析请求参数
	var user UserModel
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "Invalid request body"})
		return
	}
	// 创建用户
	result := DB.Create(&user)
	if result.Error != nil {
		// 处理创建失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User creation failed"})
	}
	// 检查创建结果,受影响的行数(应为1)
	if result.RowsAffected == 1 {
		// 返回创建成功的用户
		c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User created successfully"})
	} else {
		// 返回创建失败
		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User creation failed"})
	}
}

func getUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 返回用户
		c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User found"})
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

func updateUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 更新用户
		if err := c.ShouldBindJSON(&user); err != nil {
			c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "Invalid request body"})
			return
		}
		result = DB.Save(&user)
		if result.Error != nil {
			// 处理更新失败的错误
			log.Println(result.Error)
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User update failed"})
		}
		// 检查更新结果,受影响的行数(应为1)
		if result.RowsAffected == 1 {
			// 返回更新成功的用户
			c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User updated successfully"})
		} else {
			// 返回更新失败
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User update failed"})
		}
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

func deleteUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 删除用户
		result = DB.Delete(&user, id)
		if result.Error != nil {
			// 处理删除失败的错误
			log.Println(result.Error)
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User deletion failed"})
		}
		// 检查删除结果,受影响的行数(应为1)
		if result.RowsAffected == 1 {
			// 返回删除成功的用户
			c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User deleted successfully"})
		} else {
			// 返回删除失败
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User deletion failed"})
		}
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

func main() {
	// 示例:创建数据表(如果不存在)
	DB.AutoMigrate(&UserModel{})
	// 创建gin路由
	router := gin.Default()
	// Swagger UI endpoint
	router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	// 定义user的路由分组
	userGroup := router.Group("/users")
	{
		userGroup.GET("/", listUser)
		userGroup.POST("/", createUser)
		userGroup.GET("/:id", getUser)
		userGroup.PUT("/:id", updateUser)
		userGroup.DELETE("/:id", deleteUser)
	}

	// 启动HTTP服务器并监听在8080端口
	router.Run(":8080")

}

安装swagger

使用Go的包管理工具go get命令从GitHub仓库下载并安装swagger。在命令行终端中执行:

go get -u github.com/swaggo/swag/cmd/swag
go get -u github.com/swaggo/files
go get -u github.com/swaggo/gin-swagger

添加swagger注释

在main函数路由内部使用swagger

// Swagger UI endpoint
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

在main函数上方添加swagger注释

// @title Golang Example API
// @version 1
// @description This is a sample server for a Golang project.
// @host localhost:8080
// @BasePath /

给路由函数添加swagger注释
在listUser函数上添加swagger注释

// @Tags Users
// @Summary 查询用户列表
// @Produce json
// @Param page query int false "页码"
// @Param pageSize query int false "每页数量"
// @Success 200 {object} Response
// @Failure 500 {object} Response
// @Router /users [get]

在createUser函数上添加swagger注释

// @Tags Users
// @Summary 创建用户
// @Accept json
// @Produce json
// @Param user body UserRequest true "用户信息"
// @Success 200 {object} Response
// @Failure 400 {object} Response
// @Failure 500 {object} Response
// @Router /users [post]

在getUser函数上添加swagger注释

// @Tags Users
// @Summary 查询用户详情
// @Produce json
// @Param id path int true "用户ID"
// @Success 200 {object} Response
// @Failure 404 {object} Response
// @Failure 500 {object} Response
// @Router /users/{id} [get]

在updateUser函数上添加swagger注释

// @Tags Users
// @Summary 更新用户信息
// @Accept json
// @Produce json
// @Param id path int true "用户ID"
// @Param user body UserRequest true "用户信息"
// @Success 200 {object} Response
// @Failure 400 {object} Response
// @Failure 404 {object} Response
// @Failure 500 {object} Response
// @Router /users/{id} [put]

在deleteUser函数上添加swagger注释

// @Tags Users
// @Summary 删除用户
// @Produce json
// @Param id path int true "用户ID"
// @Success 200 {object} Response
// @Failure 404 {object} Response
// @Failure 500 {object} Response
// @Router /users/{id} [delete]

生成swagger文档

在项目根目录下运行swag命令生成 Swagger JSON 和 YAML 文件:
当main.go文件在项目根目录下时,执行以下代码

swag init

image.png
当main.go文件在项目根目录下的src/cmd目录下时,执行以下代码,-g后面跟着的是main.go的相对于项目根目录的相对路径,你可以替换为你的main.go文件所在的路径

swag init -g ./src/cmd/main.go -o ./docs  #初始化文档

设置跨域

Gin v1.x 及更高版本已经内置了 CORS 中间件。只需在路由设置中添加 gin-contrib/cors 包提供的中间件即可。确保已通过 go get 安装该包:

go get -u github.com/gin-contrib/cors

然后在你的应用初始化代码中导入并配置 CORS 中间件(一般写在路由最上方):

// 启用跨域请求, 允许所有源。一般写在路由最上方
router.Use(cors.Default())

引入swagger包

切记要main.go引入docs文件夹,防止大家出现如下错误
image.png
image.png
main.go引入docs文件夹

_ "your-project-name/docs" //这里的your-project-name是你的项目名

下图是我的引用
image.png

执行

在命令台项目根目录下执行go run .\main.go,其中.\main.go为main.go的相对于项目的目录
或者在main.go文件上右键执行Run ‘go build main.go’

go run main.go

打开浏览器输入http://127.0.0.1:8080/swagger/index.html
出现下图即为成功:
image.png

源码

package main

import (
	"fmt"
	_ "gin-gorm-crud/docs"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
	"net/http"
	"strconv"
)

// 全局变量,用于存储数据库连接
var DB *gorm.DB

// 定义一个结构体来映射数据库中的表
type UserModel struct {
	// 使用 `comment:用户表主键` 设置字段的备注信息
	ID uint `json:"id" gorm:"primaryKey"`
	// 使用 `type:varchar(20)` 设置字段类型及长度
	// 使用 `not null` 设置字段为非空
	// 使用 `comment:用户名` 设置字段的备注信息
	Name string `json:"user_name" gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`
	// 使用 `size:10` 设置字段的长度
	// 使用 `comment:年龄` 设置字段的备注信息
	Age int `json:"age" gorm:"column:age;size:10;comment:年龄;"`
}

// 定义一个结构体来映射分页查询的数据
type Pagination struct {
	// 当前页码
	Page int `json:"page"`
	// 每页数量
	PageSize int `json:"pageSize"`
	// 总页数
	TotalPages int `json:"totalPages"`
	// 总记录数
	TotalCount int `json:"totalCount"`
}

// 定义一个结构体来映射查询用户列表的返回数据
type UserData struct {
	// 用户列表
	Users []UserModel `json:"users"`
	// 分页信息
	Pagination Pagination `json:"pagination"`
}

// 定义一个结构体来映射返回的数据
type Response struct {
	// 状态码
	Code int `json:"code"`
	// 数据
	Data interface{} `json:"data"`
	// 消息
	Msg string `json:"msg"`
}

type UserRequest struct {
	// 使用 `type:varchar(20)` 设置字段类型及长度
	// 使用 `not null` 设置字段为非空
	// 使用 `comment:用户名` 设置字段的备注信息
	Name string `json:"user_name" gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`
	// 使用 `size:10` 设置字段的长度
	// 使用 `comment:年龄` 设置字段的备注信息
	Age int `json:"age" gorm:"column:age;size:10;comment:年龄;"`
}

// 将users表名更改为自定义表名sys_user
func (UserModel) TableName() string {
	return "sys_user"
}

// 初始化数据库连接
func init() {
	username := "root"
	password := "123456"
	host := "127.0.0.1"
	port := "3306"
	database := "test"
	// mysql打印日志
	var mysqlLogger logger.Interface
	mysqlLogger = logger.Default.LogMode(logger.Info)
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, database)
	//_, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: mysqlLogger, // mysql打印日志
	})
	if err != nil {
		log.Fatalf("Failed to connect to the database: %v", err)
	}
	// 连接成功后,可以进行数据库操作
	fmt.Println("Connected to the database successfully.")
	DB = db
}

// @Tags Users
// @Summary 查询用户列表
// @Produce json
// @Param page query int false "页码"
// @Param pageSize query int false "每页数量"
// @Success 200 {object} Response
// @Failure 500 {object} Response
// @Router /users/ [get]
func listUser(c *gin.Context) {
	// 从请求中获取page和pageSize参数,设置默认值
	pageStr, pageSizeStr := c.Query("page"), c.Query("pageSize")
	page, errPage := strconv.Atoi(pageStr)
	pageSize, errPageSize := strconv.Atoi(pageSizeStr)

	if errPage != nil || page < 1 {
		page = 1
	}
	if errPageSize != nil || pageSize < 1 {
		pageSize = 10
	}

	var users []UserModel
	var totalCount int64
	DB.Model(&UserModel{}).Count(&totalCount) // 计算总用户数

	totalPages := int((totalCount + int64(pageSize) - 1) / int64(pageSize)) // 计算总页数
	offset := (page - 1) * pageSize

	result := DB.Offset(offset).Limit(pageSize).Find(&users) // 分页查询用户

	if result.Error != nil {
		c.JSON(500, Response{Code: 500, Data: nil, Msg: "Database error"})
		return
	}

	// 构建分页信息
	pagination := Pagination{
		Page:       page,
		PageSize:   pageSize,
		TotalPages: totalPages,
		TotalCount: int(totalCount),
	}

	userData := UserData{
		Users:      users,
		Pagination: pagination,
	}

	// 添加分页信息到响应中
	c.JSON(200, Response{Code: 200, Data: userData, Msg: "Success"})
}

// @Tags Users
// @Summary 创建用户
// @Accept json
// @Produce json
// @Param user body UserRequest true "用户信息"
// @Success 200 {object} Response
// @Failure 400 {object} Response
// @Failure 500 {object} Response
// @Router /users/ [post]
func createUser(c *gin.Context) {
	// 解析请求参数
	var user UserModel
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "Invalid request body"})
		return
	}
	// 创建用户
	result := DB.Create(&user)
	if result.Error != nil {
		// 处理创建失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User creation failed"})
	}
	// 检查创建结果,受影响的行数(应为1)
	if result.RowsAffected == 1 {
		// 返回创建成功的用户
		c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User created successfully"})
	} else {
		// 返回创建失败
		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User creation failed"})
	}
}

// @Tags Users
// @Summary 查询用户详情
// @Produce json
// @Param id path int true "用户ID"
// @Success 200 {object} Response
// @Failure 404 {object} Response
// @Failure 500 {object} Response
// @Router /users/{id} [get]
func getUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 返回用户
		c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User found"})
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

// @Tags Users
// @Summary 更新用户信息
// @Accept json
// @Produce json
// @Param id path int true "用户ID"
// @Param user body UserRequest true "用户信息"
// @Success 200 {object} Response
// @Failure 400 {object} Response
// @Failure 404 {object} Response
// @Failure 500 {object} Response
// @Router /users/{id} [put]
func updateUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 更新用户
		if err := c.ShouldBindJSON(&user); err != nil {
			c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "Invalid request body"})
			return
		}
		result = DB.Save(&user)
		if result.Error != nil {
			// 处理更新失败的错误
			log.Println(result.Error)
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User update failed"})
		}
		// 检查更新结果,受影响的行数(应为1)
		if result.RowsAffected == 1 {
			// 返回更新成功的用户
			c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User updated successfully"})
		} else {
			// 返回更新失败
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User update failed"})
		}
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

// @Tags Users
// @Summary 删除用户
// @Produce json
// @Param id path int true "用户ID"
// @Success 200 {object} Response
// @Failure 404 {object} Response
// @Failure 500 {object} Response
// @Router /users/{id} [delete]
func deleteUser(c *gin.Context) {
	// 解析请求参数
	id := c.Param("id")
	// 查询用户
	var user UserModel
	result := DB.First(&user, id)
	if result.Error != nil {
		// 处理查询失败的错误
		log.Println(result.Error)
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
	// 检查查询结果,查询到的用户数量(应为1)
	if result.RowsAffected == 1 {
		// 删除用户
		result = DB.Delete(&user, id)
		if result.Error != nil {
			// 处理删除失败的错误
			log.Println(result.Error)
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User deletion failed"})
		}
		// 检查删除结果,受影响的行数(应为1)
		if result.RowsAffected == 1 {
			// 返回删除成功的用户
			c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User deleted successfully"})
		} else {
			// 返回删除失败
			c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User deletion failed"})
		}
	} else {
		// 返回用户未找到
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
	}
}

// @title Golang Example API
// @version 1
// @description This is a sample server for a Golang project.
// @host localhost:8081
// @BasePath /
func main() {
	// 示例:创建数据表(如果不存在)
	DB.AutoMigrate(&UserModel{})
	router := gin.Default()
	// 启用跨域请求, 允许所有源。一般写在路由最上方
	router.Use(cors.Default())
	// Swagger UI endpoint
	router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	// 定义user的路由分组
	userGroup := router.Group("/users")
	{
		userGroup.GET("/", listUser)
		userGroup.POST("/", createUser)
		userGroup.GET("/:id", getUser)
		userGroup.PUT("/:id", updateUser)
		userGroup.DELETE("/:id", deleteUser)
	}

	// 启动HTTP服务器并监听在8080端口
	router.Run(":8081")
}

总结

本文创建一个新的Go项目,其中包括使用GORM进行MySQL数据库的CRUD(创建、读取、更新、删除)操作。首先,配置GORM以连接MySQL数据库,并定义所需的模型结构体。这些结构体将映射到数据库的表。然后,实现对这些表的CRUD操作,包括添加新记录、查询记录、更新已存在的记录以及删除记录。

接下来,使用Gin框架来构建HTTP服务器和路由。为每种CRUD操作编写相应的接口,这样可以通过HTTP请求对数据库进行操作。Gin框架使得这些接口的编写和管理变得简洁高效。

最后,为了提高API的可用性和维护性,整合Swagger到项目中。

  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值