写在前面
项目地址
个人认为GORM 指南
这个网站是相比较之下最为清晰的框架介绍
但是它在环境搭建阶段对于初学者而言不是很友好,尤其是使用mysql
指令稍有不同,以及更新的方法和依赖问题都是很让人头疼的,而且这些报错并非逻辑上的,往往是网络端口,数据库创建等没有接触过的内容,因此我建议可以在学习使用增删改查的操作时看框架教程,配置环境使用以下的学习步骤:
-
首先,下载
mysql
,以及三选一mysqlshell
,navicat
,dbreaver
(个人感觉第二个的破解版手感是最丝滑的),对于初学一个东西,我认为可视化是最好的帮助和激励 -
在创建和连接数据库的时候,搜一下“Navicat使用快速入门教程”,对于数据库连接不成功的情况,往往是因为没有启动服务,这个在任务管理器->服务->
mysql90
(或80),找到之后右键手动打开即可,简单学一下建表(增删改查都看一下也可以,大概十几分钟就搞定) -
之后,使用下面两个命令在项目中搭建
gorm
环境go get -u gorm.io/gorm go get -u gorm.io/driver/mysql
-
然后,按照下面的文件结构去添加文件夹和文件即可,由于版本的原因,我直接上传所有新增文件,并且以注释的形式去解释每部分的作用
文件及解析
dao.go
package dao
import (
"Ranking/config"
"Ranking/pkg/logger"
"gorm.io/driver/mysql" // 引入 MySQL 驱动
"gorm.io/gorm" // 引入 Gorm
"time"
)
var (
Db *gorm.DB
err error
)
func init() {
// 使用 gorm.Open 打开 MySQL 数据库连接
Db, err = gorm.Open(mysql.Open(config.Mysqldb), &gorm.Config{})
if err != nil {
logger.Error(map[string]interface{}{"mysql connect error": err.Error()})
return // 连接失败,提前返回
}
// 获取底层的 sql.DB
sqlDB, err := Db.DB()
if err != nil {
logger.Error(map[string]interface{}{"get DB instance error": err.Error()})
return // 获取 DB 实例失败,提前返回
}
// 配置连接池参数
sqlDB.SetMaxIdleConns(10) // 设置最大空闲连接数
sqlDB.SetMaxOpenConns(100) // 设置最大打开连接数
sqlDB.SetConnMaxLifetime(time.Hour) // 设置连接的最大可重用时长
}
models包user.go
package models
import "Ranking/dao"
type User struct {
Id int
Username string
}
func (User) TableName() string {
return "user"
}
// GetUsersTest 根据用户ID获取用户信息
func GetUsersTest(id int) (User, error) {
var user User
//where在 SQL 中生成一个 WHERE 子句,以便查找满足条件的记录,?是占位符
//first方法用于查找单个记录,如果找到,则返回该记录,否则返回错误
err := dao.Db.Where("id =?", id).First(&user).Error
return user, err
}
controllers->user.go
重写一个方法
func (u UserController) GetUserInfo(c *gin.Context) {
idStr := c.Param("id")
name := c.Param("name")
id, _ := strconv.Atoi(idStr)
user, _ := models.GetUsersTest(id)
ReturnSuccess(c, 0, name, user, 1)
}
路由(调用getuserinfo
,需要传入id)
user.GET("/info/:id", controllers.UserController{}.GetUserInfo)
最需要注意的就是db文件的配置
运行检查:
数据库构建:
id是创建的数据库里面的id键值(主键)
增删改查的实现
实现思路:
代码
可以参考项目地址
router.go
package router
import (
"Ranking/controllers"
"Ranking/pkg/logger"
"github.com/gin-gonic/gin"
"net/http"
)
// 路由 函数的名字要大写,这样才可以被其他包访问!
func Router() *gin.Engine {
//创建一个路由的实例
r := gin.Default()
//日志
r.Use(gin.LoggerWithConfig(logger.LoggerToFile()))
r.Use(logger.Recover)
//实现GET路由 获取
r.GET("/hello", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "hello world")
})
//创建这样一个组,简化代码
user := r.Group("/user")
{
//查询单条数据
user.GET("/info/:id", controllers.UserController{}.GetUserInfo)
//查询列表数据
user.POST("/list", controllers.UserController{}.GetList)
//添加数据
user.POST("/add", controllers.UserController{}.AddUser)
//修改数据
user.POST("/update", controllers.UserController{}.UpdateUser)
//删除单个用户的数据
user.POST("/delete", controllers.UserController{}.DeleteUser)
//获取用户列表
user.GET("/info/list", controllers.UserController{}.GetAllUsers)
user.DELETE("/delete", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "user delete")
})
}
order := r.Group("/order")
{
order.GET("/list", controllers.OrderController{}.GetList)
}
return r
}
控制user.go
package controllers
import (
"Ranking/models"
"Ranking/pkg/logger"
"fmt"
"github.com/gin-gonic/gin"
"strconv"
)
// 实现关于用户的功能
type UserController struct{}
func (u UserController) GetUserInfo(c *gin.Context) {
idStr := c.Param("id")
name := c.Param("name")
id, _ := strconv.Atoi(idStr)
user, _ := models.GetUsersTest(id)
ReturnSuccess(c, 0, name, user, 1)
}
func (u UserController) GetList(c *gin.Context) {
// 程序员手动设置的日志
logger.Write("日志信息", "user")
defer func() {
if err := recover(); err != nil {
fmt.Println("捕获异常:", err)
}
}()
num1, num2 := 1, 0
num3 := num1 / num2
ReturnUserGetListError(c, 404, num3)
}
func (u UserController) AddUser(c *gin.Context) {
//logger.Write("日志信息", "user")
username := c.DefaultPostForm("username", "")
// 输入检查
if username == "" {
ReturnError(c, 400, "用户名不能为空")
return
}
id, err := models.AddUser(username)
if err != nil {
ReturnError(c, 400, "用户添加失败"+err.Error()) // 返回具体错误信息
return
}
ReturnSuccess(c, 0, "用户添加成功", id, 1)
}
// 更新用户名
func (u UserController) UpdateUser(c *gin.Context) {
//获取用户信息
username := c.DefaultPostForm("username", "")
idStr := c.DefaultPostForm("id", "")
id, _ := strconv.Atoi(idStr)
//调用方法更新数据库中的用户名
models.UpdateUser(id, username)
ReturnSuccess(c, 0, "用户更新成功", true, 1)
}
// 删除用户
func (u UserController) DeleteUser(c *gin.Context) {
//获取id
idStr := c.DefaultPostForm("id", "")
id, _ := strconv.Atoi(idStr)
//调用方法删除数据库中的用户
err := models.DeleteUser(id)
if err != nil {
ReturnError(c, 404, "用户删除失败"+err.Error())
}
ReturnSuccess(c, 0, "用户删除成功", true, 1)
}
//func (u UserController) GetAllUsers(c *gin.Context) {
// users, err := models.GetAllUsers()
// if err != nil {
// ReturnError(c, 404, "用户列表获取失败"+err.Error())
// }
// ReturnSuccess(c, 0, "用户列表获取成功成功", users, 1)
//}
func (u UserController) GetAllUsers(c *gin.Context) {
users, err := models.GetAllUsers()
if err != nil {
ReturnError(c, 404, "用户列表获取失败: "+err.Error())
return // 添加 return 结束函数的执行
}
// 处理成功的情况,避免重复的“成功”字样
ReturnSuccess(c, 0, "用户列表获取成功", users, 1)
}
注意,在common.go
中有需要新建的返回值方法
模块user.go
package models
import (
"Ranking/dao"
"fmt"
)
type User struct {
Id int
Username string
}
func (User) TableName() string {
return "user"
}
// GetUsersTest 根据用户ID获取用户信息
func GetUsersTest(id int) (User, error) {
var user User
//where在 SQL 中生成一个 WHERE 子句,以便查找满足条件的记录,?是占位符
//first方法用于查找单个记录,如果找到,则返回该记录,否则返回错误
err := dao.Db.Where("id =?", id).First(&user).Error
return user, err
}
// 调用该方法,存储一个新用户 返回主键和错误信息(controllers包中调用)
func AddUser(username string) (int, error) {
user := User{Username: username}
err := dao.Db.Create(&user).Error
if err != nil {
return 0, fmt.Errorf("添加用户时出错:%w", err) // 返回详细错误
}
return user.Id, nil
}
func UpdateUser(id int, username string) {
dao.Db.Model(&User{}).Where("id = ?", id).Update("username", username)
}
// DeleteUser 根据用户ID(主键)删除用户
func DeleteUser(id int) error {
err := dao.Db.Delete(&User{}, id).Error
return err
}
//func GetAllUsers() ([]User, error) {
// var users []User
// //没存够100号 所以拿这个数来返回整个列表
// err := dao.Db.Where("id < 100", 100).Find(&users).Error
// return users, err
//}
func GetAllUsers() ([]User, error) {
var users []User
//没存够100号 所以拿这个数来返回整个列表
err := dao.Db.Where("id < ?", 100).Find(&users).Error
if err != nil {
return nil, err
}
return users, nil
}