上文《Go语言Web开发系列(十四)Gin web封装统一返回结构体》我们统一封装了结构返回体。但是在代码里面我们可以看到很多的err判断,此时的话,我们一般希望有一个地方能统一处理这种error,并且返回统一的结构体。所以这里我们演示下在Gin web框架中处理全局异常。
这里处理全局异常比较简单,我们定义一个中间件即可,例如:
func Recover(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
// 返回统一的Json风格
Error(c, 500, err)
//终止后续操作
c.Abort()
}
}()
//继续操作
c.Next()
}这个中间件的话主要是结合panic来使用的,当系统出现recover的时候,我们就获取到对应的错误信息,然后组装成统一的json返回给前台。
在gin里面这里的中间件是全局的,所以我们使用:
router.Use(Recover)
就可以了,在代码里面只要出现error,我们就全部使用panic来处理,例如:
if err != nil {
panic(err.Error())
}这里我们演示一下,把登录的接口查询的sql语句里面的表修改为users1,但是我们数据库是不存在users1表的,所以这里会直接报错的,示例图如下:
然后我们把项目启动起来,登录一下,就可以看到错误信息返回了:
是不是很简单?
备注:
1、这里处理全局异常主要是使用中间件来实现的。 2、所有的error都需要使用panic函数来处理。 3、把原始的err错误提示字符串传递给panic。
最后我们附上修改后的完整代码:
// demo1 project main.go
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
"time"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
)
type Users struct {
Id int
Name string
NickName string
}
/*
*
创建数据库连接
*/
func connectToDatabase() (*sql.DB, error) {
db, err := sql.Open("mysql", "root:123456@tcp(192.168.31.217:33306)/test")
if err != nil {
return nil, err
}
db.SetConnMaxLifetime(time.Second * 3600 * 8)
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
err = db.Ping()
if err != nil {
return nil, err
}
return db, nil
}
func main() {
//创建数据库连接
db, err := connectToDatabase()
if err != nil {
panic(err)
}
//程序关闭的时候需要关闭掉数据库连接
defer db.Close()
router := gin.Default()
router.Use(Recover)
//用户登录
router.POST("/login", func(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")
log.Println("获取到的用户名和密码是:", username, password)
rows, err := db.Query("SELECT id FROM users1 WHERE username = ? and password = ?", username, password)
if err != nil {
panic(err.Error())
}
defer rows.Columns()
if rows.Next() == true {
Ok(c, 200, "登录成功", nil)
} else {
Error(c, 400, "用户名或者密码不正确")
}
})
//用户注册
router.POST("/register", func(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")
nickname := c.PostForm("nickname")
log.Println("获取到的用户名和密码是:", username, password)
inserSql := "insert into users(username,password,nickname) values(?,?,?)"
// 创建事务
tx, err := db.Begin()
if err != nil {
panic(err)
}
// 执行插入语句
_, err = tx.Exec(inserSql, username, password, nickname) //value输入具体的值
if err != nil {
panic(err)
}
// 提交事务
err = tx.Commit()
if err != nil {
panic(err)
}
Ok(c, 200, "注册成功", nil)
})
//获取用户信息
router.POST("/getUinfo/:username", func(c *gin.Context) {
username := c.Param("username")
var user Users
querySql := "SELECT id, username, nickname FROM users WHERE username = ?"
err = db.QueryRow(querySql, username).Scan(&user.Id, &user.Name, &user.NickName)
if err != nil {
panic(err)
}
Ok(c, 200, "登录成功", user)
})
//修改用户信息
router.POST("/updateUinfo", func(c *gin.Context) {
username := c.PostForm("username")
nickname := c.PostForm("nickname")
updateSql := "update users set nickname= ? WHERE username = ?"
_, err = db.Exec(updateSql, nickname, username)
if err != nil {
panic(err)
}
Ok(c, 200, "修改成功", nil)
})
//删除用户信息
router.POST("/deleteU/:username", func(c *gin.Context) {
username := c.Param("username")
updateSql := "delete from users WHERE username = ?"
_, err = db.Exec(updateSql, username)
if err != nil {
panic(err)
}
Ok(c, 200, "删除成功", nil)
})
router.Run(":9000")
}
func Error(c *gin.Context, code int, msg any) {
c.JSON(http.StatusOK, gin.H{
"code": code,
"msg": msg,
})
}
func Ok(c *gin.Context, code int, msg string, data any) {
c.JSON(http.StatusOK, gin.H{
"code": code,
"msg": msg,
"data": data,
})
}
func Recover(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
// 返回统一的Json风格
Error(c, 500, err)
//终止后续操作
c.Abort()
}
}()
//继续操作
c.Next()
}










还没有评论,来说两句吧...