Gin是一个使用 Go 语言开发的 Web 框架,它提供类似 Martini 的 API,但性能更佳,速度提升高达 40 倍(基于 httprouter 实现)。
介绍
- 擅长 API 接口高并发
开发
- Golang 开发中的热加载工具
- Swagger
- gin 运行的三种模式,参考
DebugMode默认模式,比ReleaseMode多了一些额外的错误信息ReleaseMode发布模式优化调试输出,如路由日志不会输出到终端TestMode
- 设置方式
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)vscode 自动加载?
组成
type User Struct {Username string \`form: "username" json: "username"\` }
- 首字母大写
- GET 示例
- GET /user?username=abc
- var u User; if err:=c.ShouldBind(&u); err == nil {}
- POST 示例
- POST /user {"username": "abc"}
- var u User; if err:=c.ShouldBind(&u); err == nil {}
- 获取原始数据:`b, err := c.GetRawData()`,从 c.Request.Body 读取请求的数据
- 路由组
- `v1 := r.Group("/api/v1")`
- `v1.Get("/user", GetUser)`
- 自动以控制器
- 项目较大时,需要对控制器分组
- controller/admin/UsersController.go
- 中间件:Gin 框架的中间件允许开发者子啊处理请求时,加入自己的钩子函数(Hooks) - 常见作用 - 登录认证 - 权限校检 - 数据分页 - 记录日志 - 耗时统计 - 等 - `gin.HandlerFunc` 类型,注册路由时,可以指定多个回调函数,最后一个函数前的都称中间件 - `c.Next()` 调用该请求的剩余处理程序,多个使用该方法时,按入栈的倒序依次执行 - `c.Abort()` 终止调用该请求的剩余处理程序 - 分类 - 全局中间件:`r.Use(XXXMiddleware1, XXXMiddleware2, ...)` - 路由分组中间件: - `r.Group("/v1", XXXMiddleware1, ...)` - `v1Group := r.Group("/v1"); v1Group.use(XXXMiddleware1, XXXMiddleware2, ...)` - 中间件和控制器之间共享数据 - `c.Set("key", "value");` - `v, err := c.Get("key");` - 若在中间件使用 goroutine,不能使用原始的 `c *gin.Context`,必须使用只读副本 `cc := c.Copy()` - 异常处理 `gin.Context.Errors` - `gin.Context.Error(err)` attaches an error to the current context - 可以写一个 `gin.Context.Errors` 的中间件,统一处理错误
示例
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 默认路由引擎
r := gin.Default()
// 路由配置
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
// 启动 HTTP 服务
//r.Run("0.0.0.0:8000")
//r.Run(":8000")
_ = r.Run()
// curl http://127.0.0.1:8080/ping
//{"message":"pong"}
}
session
日志
集成 swag
- Swag将 Go 的注释转换为 Swagger2.0 文档
- 源码
- 如何与 Gin 集成
- 通用 api 信息
- 安全性 支持 Basic auth、API key auth、Oauth2 等
- 示例
- 自定义 API 认证
- 响应对象中的模型组合
- swaggo/gin-swagger gin 中间件,用 Swagger 2.0 自动生成 RESTful API 文档
go install github.com/swaggo/swag/cmd/swag@latest
# help
swag -h
swag init -h
swag fmt -h
# 默认指定 main.go 文件
swag init
# 手动指定文件
swag init -g http/api.go
# 自动格式化 swag 格式文件
swag fmt- 方法注释,参考
// @Param enumstring query string false "string enums" Enums(A, B, C)
// @Param enumint query int false "int enums" Enums(1, 2, 3)
// @Param enumnumber query number false "int enums" Enums(1.1, 1.2, 1.3)
// @Param string query string false "string valid" minlength(5) maxlength(10)
// @Param int query int false "int valid" minimum(1) maximum(10)
// @Param default query string false "string default" default(A)
// @Param collection query []string false "string collection" collectionFormat(multi)
// @Param extensions query []string false "string collection" extensions(x-example=test,x-nullable)
// GetStringByInt example
//
// @Deprecated
// @Summary Add a new pet to the store
// @Description get string by ID
// @ID get-string-by-int
// @Accept json
// @Produce json
// @Param some_id path int true "Some ID"
// @Param some_id body web.Pet true "Some ID"
// @Success 200 {string} string "ok"
// @Failure 400 {object} web.APIError "We need ID!!"
// @Failure 404 {object} web.APIError "Can not find ID"
// @Router /testapi/get-string-by-int/{some_id} [get]
// GetUser example
//
// @Summary Read user from the store
// @Tags admin
// @Accept json
// @Produce json
// @Param id path int true "User Id"
// @Success 200 {object} api.User
// @Failure 400 {object} api.APIError "We need ID!!"
// @Failure 404 {object} api.APIError "Can not find ID"
// @Router /admin/user/{id} [get]
func GetUser(w http.ResponseWriter, r *http.Request) {
// write your code
}
// JSONResult的data字段类型将被proto.Order类型替换
@success 200 {object} jsonresult.JSONResult{data=proto.Order} "desc"
@success 200 {object} jsonresult.JSONResult{data=[]proto.Order} "desc"
@success 200 {object} jsonresult.JSONResult{data=string} "desc"
@success 200 {object} jsonresult.JSONResult{data=[]string} "desc"- golang 标记方法废弃的方法
// Deprecated: xxx
func ...集成 validator
- 源码
- 示例
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Username string `validate:"min=5,max=16"`
Age uint8 `validate:"gte=1,lte=10"`
Sex string `validate:"oneof=female male"`
}
func main() {
validate := validator.New()
user1 := User{Username: "xianbin", Age: 18, Sex: "null"}
err := validate.Struct(user1)
if err != nil {
fmt.Println(err)
}
user2 := User{Username: "xianbin888", Age: 18, Sex: "male"}
err = validate.Struct(user2)
if err != nil {
fmt.Println(err)
}
}
- 字符串约束
excludesall不包含参数中任意的 UNICODE 字符,例如excludesall=xianbinexcludesrune不包含参数表示的 rune 字符,例如excludesrune=xianbinstartswith以参数子串为前缀,例如startswith=hiendswith以参数子串为后缀,例如endswith=byecontains=包含参数子串,例如contains=emailcontainsany包含参数中任意的 UNICODE 字符,例如containsany=xianbincontainsrune包含参数表示的 rune 字符,例如containsrune=xianbinexcludes不包含参数子串,例如excludes=email
- 常用 tag 介绍
ne不等于参数值,例如ne=5gt大于参数值,例如gt=5gte大于等于参数值,例如gte=50lt小于参数值,例如lt=50lte小于等于参数值,例如lte=50oneof只能是列举出的值其中一个,这些值必须是数值或字符串,以空格分隔,如果字符串中有空格,将字符串用单引号包围,例如oneof=male femaleeq等于参数值,注意与 len 不同。对于字符串,eq 约束字符串本身的值,而 len 约束字符串长度,例如eq=10len等于参数值,例如len=10max小于等于参数值,例如max=10min大于等于参数值,例如min=10
- Fields 约束
eqfield定义字段间的相等约束,用于约束同一结构体中的字段,例如eqfield=Passwordeqcsfield约束统一结构体中字段等于另一个字段(相对),确认密码时可以使用,例如eqfiel=ConfirmPasswordnefield用来约束两个字段是否相同,确认两种颜色是否一致时可以使用,例如nefield=Color1necsfield约束两个字段是否相同(相对)
- 常用约束
unique指定唯一性约束,不同类型处理不同- 对于
map,unique约束没有重复的值 - 对于数组和切片,
unique没有重复的值 - 对于元素类型为结构体的碎片,
unique约束结构体对象的某个字段不重复,使用unique=field指定字段名
- 对于
email邮件格式,无需加任何指定omitempty字段未设置,则忽略-跳过该字段,不检验|使用多个约束,只需要满足其中一个,例如rgb|rgbarequired字段必须设置,不能为默认值
其他
- gin 官方示例
- gin-gonic/examples 一个用于托管 Gin 示例和教程的存储库
- gin 相关框架
- https://github.com/go-admin-team/go-admin 基于 Gin + Vue + Element UI & Arco Design & Ant Design 的前后端分离权限管理系统脚手架
- https://github.com/go-admin-team/go-admin-ui
- https://github.com/GoAdminGroup/go-admin
- Sponge 提供一站式项目开发解决方案,涵盖代码生成、开发、测试、API 文档和部署等,帮助开发者以"低代码"方式轻松构建稳定可靠的高性能后端服务(包括 RESTful API、gRPC、HTTP+gRPC、gRPC Gateway 等)
最近更新
最新评论