文章目录
前言
大概内容:
序言
主要内容概述如下:
-
项目初始化:首先着手创建一个新的Go项目,确保具备进行后续开发工作的基础框架。
-
CRUD实现:在构建的Go项目中,使用gorm着手实现一组用于MySQL数据的crud操作。此阶段涵盖了创建(Create)、检索(Read)、更新(Update)与删除(Delete)功能的完整实现,确保每个接口均能准确对应相应的数据操作。
-
CRUD接口实现:在构建的Go项目中,使用gin着手实现一组用于模拟数据操作的RESTful API接口。此阶段涵盖了创建(Create)、检索(Read)、更新(Update)与删除(Delete)功能的完整实现,确保每个接口均能准确对应相应的数据操作。
-
文档编制:最后,为已实现的接口集编写详尽的Swagger文档。利用Swagger的标准化描述格式,清晰阐述各个接口的路由、请求方法、请求参数、预期响应结构、HTTP状态码含义等关键信息,形成一套完整的API参考手册。此举旨在提升项目的技术透明度,方便团队内外的开发者查阅、理解和调用接口,促进代码的可维护性与协作效率。
操作系统:Windows 11。
开发环境:已配备Goland作为Go语言的主要集成开发环境(IDE)。
编程语言与框架:已预先安装Go编程语言(全称为Golang),这是实验所依赖的核心编程环境。在本次实验中,我们选用Go语言生态系统中的Gin框架作为主要的Web开发框架进行操作,以及gorm框架作为主要的数据库开发框架进行操作。选用的数据库为MySQL
提示:以下是本篇文章正文内容,下面案例仅供参考
新建项目
点击New Project
选择左侧栏的Go->填写Location->填写Environment->点击右下角的Create
其中绿色框起来的是你的项目所在的文件目录,红色框起来的是你的项目目录
蓝色框起来的是第三方代理:goproxy.cn,是一个在中国广泛使用的Go语言代理服务GOPROXY=https://goproxy.cn,direct
如图,你的项目已经创建成功了
在根目录下右键->new->Go File->填写main,然后回车即可
gorm连接数据库
安装 GORM 及 MySQL 驱动
确保已经安装了 GORM 库及其 MySQL 驱动。如果您尚未安装,可以使用以下命令进行安装:
go get -u gorm.io/gorm # 安装GORM
go get -u gorm.io/driver/mysql # 安装MySQL 驱动
连接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文件,可以看到数据库连接成功
到此,你已经连接上数据库了。接下来将main主函数内部的数据库连接代码迁移到main主函数外
初始化数据库连接
新建函数init
,首先要说明的是:
在 Go 语言中,init 函数是一种特殊的函数,它在包的所有变量声明后自动执行,并且是在 main 函数执行之前运行的。每个包可以有多个 init 函数,这些函数按照它们在文件中出现的顺序依次执行。init 函数主要用于初始化操作,比如设置包级变量的初始值、检查或修复程序状态、注册、运行一次性计算等。
以下是 init 函数的几个关键特性:
- 自动执行:init 函数不需要在任何地方被显式调用,它会自动被 Go 运行时调用。
- 执行顺序:如果一个包导入了其他包,被导入包的 init 函数先于导入包执行。在同一个包中,如果有多个 init 函数(可以在同一个文件或不同文件中),它们按照它们在代码中出现的顺序执行。
- 无参数和返回值:init 函数没有参数也没有返回值。
- 多次定义:一个包可以包含多个 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{})
右键运行可以看到数据库连接成功
打开navicat可以看到,表已经成功创建
接下来主要写增加,所有查询,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)
}
右键运行,出现与下图类似的即为成功
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
当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文件夹,防止大家出现如下错误
main.go引入docs文件夹
_ "your-project-name/docs" //这里的your-project-name是你的项目名
下图是我的引用
执行
在命令台项目根目录下执行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
出现下图即为成功:
源码
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到项目中。