Gin 是一个用 Go (Golang) 编写的轻量级但功能强大的Web框架,具有极高的性能。适合开发API和微服务。
1.安装 Gin
前置任务,首先你本地需要安装过go语言环境
go get -u github.com/gin-gonic/gin
这里直接结合项目代码解析gin的主要功能:
package router
import (
"time"
"todolist/controller"
"todolist/logger"
"github.com/gin-gonic/gin"
)
// SetupRouter 设置路由
func SetupRouter() *gin.Engine {
r := gin.New()
r.Use(logger.GinLogger(), logger.GinRecovery(true))
r.GET("/", func(c *gin.Context) {
controller.ResponseSuccess(c, gin.H{
"time": time.Now(),
})
})
v1 := r.Group("/api/v1")
v1.GET("/captcha", controller.CaptchaHandler) // 获取邮箱验证码 用于注册
v1.GET("/captcha/pic", controller.CaptchaPicHandler) // 获取图片验证码 用于登录
v1.POST("/captcha/pic", controller.CheckCaptchaPicHandler) // 获取图片验证码校验 用于登录
v1.POST("/signup", controller.SignUpHadnler) // 注册
v1.POST("/login", controller.LoginHandler) // 登录
v1.GET("/accesstoken", controller.AccessTokenHandler) // 刷新accesstoken
//v1.Use(middlewares.JWTAuthMiddleware())//中间件
//RESTful风格的优势在于其简洁性和可扩展性。通过使用标准的HTTP方法,RESTful风格使得接口的设计更加清晰,易于理解和维护。
{
v1.POST("/task", controller.AddTaskHanler) // 增加task
v1.GET("/tasks", controller.GetTestByUseridHandler) // 获取tasks
v1.DELETE("/tasks", controller.DeleteTaskHandler) // 删除tasks
v1.PUT("/tasks", controller.UptateTaskHandler) // 更新tasks
}
{
v1.POST("/test", controller.AddTestHanler) // 增加test
v1.GET("/test", controller.GetTestByUseridHandler) // 根据userid获取test对象
v1.GET("/testList", controller.GetTestListHandler) // 获取test列表
v1.PUT("/test", controller.UptateTestHandler) // 更新test
v1.DELETE("/test", controller.DeleteTestHandler) // 批量删除test
}
return r
}
gin.Engine 结构体
初始引擎:
返回一个新的空白的,没有任何中间件的引擎实例
路由与路由组:
Gin 提供了灵活的路由管理功能,你可以通过 GET、POST、PUT、DELETE 等方法定义路由。路由组可以将相关的路由组织在一起,方便管理。
这里设置路由组:
中间件:
Gin 提供了轻量级的中间件支持,可以实现如身份验证、日志等功能。
定义中间件:
package middlewares
import (
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"strings"
"todolist/controller"
"todolist/controller/code"
"todolist/utils"
)
func JWTAuthMiddleware() func(c *gin.Context) {
return func(c *gin.Context) {
// 从请求体里面获取token
authHeader := c.Request.Header.Get("Authorization")
if authHeader == "" {
zap.L().Warn("Error Authorization")
controller.ResponseError(c, code.CodeNeedLogin)
c.Abort()
return
}
parts := strings.SplitN(authHeader, " ", 2)
if len(parts) != 2 && parts[0] != "Bearer" {
zap.L().Warn("Error Authorization")
controller.ResponseError(c, code.CodeInvalidToken)
c.Abort()
return
}
claims, err := utils.ParseAccessToken(parts[1])
if err != nil {
zap.L().Warn("Error Authorization")
controller.ResponseError(c, code.CodeInvalidToken)
c.Abort()
return
}
userId, email := claims.UserId, claims.Email
// 将当前请求的用户信息保存到请求的上下文c上
c.Set(controller.CtxUserIDKey, userId)
c.Set(controller.CtxUserEmail, email)
}
}
使用中间件:
gin.context:
gin.Context 上下文对象,可以方便地处理 HTTP 请求和响应的各种细节。
package controller
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"todolist/controller/code"
"todolist/dao/dmysql"
"todolist/logic"
"todolist/models"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"go.uber.org/zap"
)
// GetTestByUseridHandler 查询
func GetTestByUseridHandler(c *gin.Context) {
ids := c.Query("id")
fmt.Println("=======" + ids)
intNum, _ := strconv.Atoi(ids) //字符串转int
var uid uint = uint(intNum) // int转uint显式转换
tasks, err := dmysql.QueryTasksIdByUid(uid)
if err != nil {
zap.L().Error("Error GetTasks about logic", zap.Error(err))
ResponseError(c, code.CodeServerBusy)
return
}
tasks[0].TaskContent = "测试内容" //修改返回值
b, _ := json.Marshal(tasks) //结构体转json
s3 := string(b)
fmt.Println("tasks=======" + s3) //json转字符串
data := map[string]interface{}{
"user_id": uid,
"tasks": tasks,
}
jsonBytes, _ := json.Marshal(data)
m := string(jsonBytes)
fmt.Println("data=======" + m) //map转字符串
ResponseSuccess(c, data)
return
}
// GetTestListHandler 查询列表
func GetTestListHandler(c *gin.Context) {
ids := c.Query("id")
fmt.Println("=======" + ids)
arr := strings.Split(ids, ",") //字符串转数组
tasks, err := dmysql.QueryTasksIdByTid(arr)
if err != nil {
zap.L().Error("Error GetTasks about logic", zap.Error(err))
ResponseError(c, code.CodeServerBusy)
return
}
ResponseSuccess(c, tasks)
return
}
// AddTestHanler 新增
func AddTestHanler(c *gin.Context) {
var uid uint = 1 //创建人
p := new(models.ParamTask) //new一个空的结构体
if err := c.ShouldBindJSON(p); err != nil { //使用 ShouldBindJSON() 或 BindJSON() 解析 JSON 数据并绑定到结构体
zap.L().Error("GetTask with invalid param:ParamDate", zap.Error(err))
if errs, ok := err.(validator.ValidationErrors); ok {
ResponseErrorWithMsg(c, code.CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
ResponseError(c, code.CodeServerBusy)
return
}
logic.AddTask(uid, p)
ResponseSuccess(c, nil)
return
}
// UptateTestHandler 更新
func UptateTestHandler(c *gin.Context) {
var uid uint = 1 //修改人
p := new(models.ParamTask)
if err := c.ShouldBindJSON(p); err != nil { //使用 ShouldBindJSON() 或 BindJSON() 解析 JSON 数据并绑定到结构体
zap.L().Error("GetTask with invalid param:ParamTask", zap.Error(err))
if errs, ok := err.(validator.ValidationErrors); ok {
ResponseErrorWithMsg(c, code.CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
ResponseError(c, code.CodeServerBusy)
return
}
logic.UpdateTask(uid, p)
ResponseSuccess(c, nil)
return
}
// DeleteTestHandler 批量删除test
func DeleteTestHandler(c *gin.Context) {
var uid uint = 1 //修改人
// 2. 校验参数
p := new(models.ParamTaskIDs)
if err := c.ShouldBindJSON(p); err != nil {
zap.L().Error("DeleteTasks with invalid param:ParamTaskIDs", zap.Error(err))
if errs, ok := err.(validator.ValidationErrors); ok {
ResponseErrorWithMsg(c, code.CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
ResponseError(c, code.CodeServerBusy)
return
}
fmt.Println(p.TaskIDs) //获取id
logic.DelTasks(uid, p)
fmt.Println("-----------")
ResponseSuccess(c, nil)
return
}
Query方法:
用于获取 URL 中的查询参数。例如,对于请求http://127.0.0.1:8080/api/v1/test?id=1,可以使用以下方式获取参数:
ShouldBindJSON方法:
用于绑定 JSON 格式的请求体数据到一个结构体。
JSON方法:
用于返回一个 JSON 格式的响应。例如:
func ResponseSuccess(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, &ResponseData{
Code: code.CodeSuccess,
Msg: code.CodeSuccess.Msg(),
Data: data,
})
}
2.Gorm
Go Gorm 是一个非常强大的 Go 语言的 ORM(对象关系映射)库,它可以让开发者更加方便地在 Go 应用程序中操作数据库
安装Gorm :
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
配置连接mysql数据库
package dmysql
import (
"fmt"
"time"
"todolist/models"
"todolist/setting"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var db *gorm.DB
func InitClient(mcg *setting.MysqlConfig) (err error) {
//var dsn = "root:root@tcp(127.0.0.1:3306)/todolist?charset=utf8mb4&parseTime=True&loc=Local"
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", mcg.User, mcg.Password, mcg.Host, mcg.Port, mcg.Db)
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
// 设置日志模式为Info,将会打印出所有SQL语句
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
return err
}
sqlDB, _ := db.DB()
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)
//automigrate是gorm库中一个非常重要的功能,它可以自动创建数据库表和对应的字段,无需手动编写SQL语句。
err = db.AutoMigrate(&models.User{}, &models.Task{})
if err != nil {
return err
}
return
}
主要功能使用方法
package dmysql
import (
"fmt"
"todolist/models"
"todolist/utils"
)
// AddTask 增加task
func AddTask(task *models.Task) (*models.Task, error) {
// 1. 生成id
tid := utils.GenID()
// 2. 创建
task = &models.Task{Tid: tid, Level: task.Level, State: 0, UserID: task.UserID, TaskContent: task.TaskContent}
err := db.Create(task).Error
if err != nil {
return nil, err
}
return task, nil
}
// QueryTasksByUidAndDate 通过的uid和日期查询
func QueryTasksByUidAndDate(uid uint, date *models.ParamDate) (tasks []models.Task, err error) {
// 1. 解析日期
startDate := date.StartDate
endDate := date.EndDate
// 2. 查询数据库
err = db.Select("tid", "level", "state", "user_id", "task_content", "created_at").Where("user_id = ? and created_at >= ? and created_at < ?", uid, startDate, endDate).Find(&tasks).Error
return
}
func DelTasks(taskIDs []int64) (err error) {
fmt.Println("-------删除数据库-----")
fmt.Println(taskIDs)
err = db.Where("tid in ?", taskIDs).Delete(&models.Task{}).Error
fmt.Println(err)
fmt.Println("-------删除数据库结束-----")
return
}
// QueryTasksIdByUid 根据用户id 查询tids
func QueryTasksIdByUid(uid uint) (tids []models.Task, err error) {
err = db.Model(&models.Task{}).Debug().Select("tid", "created_at").Where("user_id = ?", uid).Find(&tids).Error
return
}
// QueryTasksIdByTid 根据tid 返回详细task
func QueryTasksIdByTid(tids []string) (task []models.Task, err error) {
err = db.Debug().Where("tid in ?", tids).Find(&task).Error
return
}
func UpdateTask(tid int64, task map[string]interface{}) (err error) {
err = db.Debug().Model(&models.Task{}).Where("tid = ?", tid).Updates(task).Error
return
}
3.demo项目地址:
https://github.com/nanist/golang
基于go+gin+redis+mysql+gorm实现的todo-list项目,适合go新手小白入门项目 功能:登录注册,日志,token验证,redis缓存,RefreshToken,todo-list的增删改查,邮件发送,图形验证码。