Go Gin 框架
简介
中文官网:https://gin-gonic.com/zh-cn/docs/introduction/
github:https://github.com/gin-gonic/gin
Gin 是一个用 Go (Golang) 编写的 Web 框架。 它具有类似 martini 的 API,性能要好得多,多亏了 httprouter,速度提高了 40 倍。 如果您需要性能和良好的生产力,您一定会喜欢 Gin
- Go 1.13 及以上版本
特性
1.快速
基于 Radix 树的路由,小内存占用。没有反射。可预测的 API 性能。
2.支持中间件
传入的 HTTP 请求可以由一系列中间件和最终操作来处理。 例如:Logger,Authorization,GZIP,最终操作 DB。
3.Crash 处理
Gin 可以 catch 一个发生在 HTTP 请求中的 panic 并 recover 它。这样,你的服务器将始终可用。例如,你可以向 Sentry 报告这个 panic!
4.JSON 验证
Gin 可以解析并验证请求的 JSON,例如检查所需值的存在。
5.路由组
更好地组织路由。是否需要授权,不同的 API 版本…… 此外,这些组可以无限制地嵌套而不会降低性能。
6.错误管理
Gin 提供了一种方便的方法来收集 HTTP 请求期间发生的所有错误。最终,中间件可以将它们写入日志文件,数据库并通过网络发送。
7.内置渲染
Gin 为 JSON,XML 和 HTML 渲染提供了易于使用的 API。
8.可扩展性
新建一个中间件非常简单,去查看示例代码吧。
hello world
初始化项目
新建一个gin_test
,文件夹,使用vsocd打开在终端输入一下命令,初始化项目
# 初始化模块
go mod init gin_test
# 下载并安装
go get -u github.com/gin-gonic/gin
main.go
创建main.go,并写入下面的代码
package main
// 将 gin 引入到代码中
import "github.com/gin-gonic/gin"
// (可选)如果使用诸如 http.StatusOK 之类的常量,则需要引入 net/http 包
// import "net/http"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}
启动
# 运行 main.go 并且在浏览器中访问 HOST_IP:8080/ping
go run main.go
访问
http://localhost:8080/ping
第一个例子完成
自定义路由
上面那个例子,路由定义和控制器处理都在main函数里面,在真实项目中显然是不可能的,难道你想看到一个文件两三万行?虽然我真的见过...,但是要尽量避免这种情况,所以我们一般把路由文件独立出来一个文件,甚至几个文件,那在Gin 里面要怎么做呢?往下看
拆分成单个路由文件
新建routes
文件夹,在此文件下新建router1.go
文件,内容如下
目录结构
│ go.mod
│ go.sum
│ main.go
└─routers
router1.go
案例
文件:routes/router1.go
package gin_test
import "github.com/gin-gonic/gin"
// 控制器方法
func helloHandler(context *gin.Context) {
context.JSON(200, "这是路由文件1")
}
// 设置路由
func SetupRouter() *gin.Engine {
// 配置路由信息
router := gin.Default()
router.GET("/router1", helloHandler)
return router
}
文件:main.go
package main
import (
"fmt"
// 引入自定义路由模块
routers "gin_test/routers"
)
func main() {
// 获取路由
router := routers.SetupRouter()
// 启动监听并打印错误
if err := router.Run(); err != nil {
fmt.Println(err)
return
}
}
启动
go run main.go
访问
http://localhost:8080/router1
到此将路由单独拆出来已经可以了
支持多个路由文件
当我们的业务规模继续膨胀,单独的一个router1.go
文件或包已经满足不了我们的需求了,我们需要按模块或者按业务拆分成多个路由文件,在Gin 中怎么实现?看下面
目录结构
│ go.mod
│ go.sum
│ main.go
└─routes
router1.go
router2.go
这时候,多个路由文件我们看做不同的模块,为了防止两个不同模块之间有同名路由
,我们最好加上路由组
官方文档:https://gin-gonic.com/zh-cn/docs/examples/grouping-routes/
我们就按文件名设置路由组吧,
- router1.go -> router1
- router2.go -> router2
这个时候我们就不能将路由初始化分到路由文件里了,而是在main函数中初始化路由,将路由器传入路由文件的方法里,也就是说路由文件只负责注册路由
案例
文件:routes/router1.go
package gin_test
import "github.com/gin-gonic/gin"
// 控制器方法
func helloHandler1(context *gin.Context) {
context.JSON(200, "这是路由文件1")
}
// 设置路由
func Router1(router *gin.Engine) {
// 设置路由组
router1 := router.Group("/router1")
{
// 注册模块1的路由
router1.GET("/hello", helloHandler1)
}
}
文件:routes/router2.go
package gin_test
import "github.com/gin-gonic/gin"
// 控制器方法
func helloHandler2(context *gin.Context) {
context.JSON(200, "这是路由文件2")
}
// 设置路由
func Router2(router *gin.Engine) {
// 设置路由组
router2 := router.Group("/router2")
{
// 注册模块2的路由
router2.GET("/hello", helloHandler2)
}
}
文件:main.go
package main
import (
"fmt"
// 引入自定义路由模块
routers "gin_test/routers"
"github.com/gin-gonic/gin"
)
func main() {
// 获取路由
router := gin.Default()
routers.Router1(router)
routers.Router2(router)
// 启动监听并打印错误
if err := router.Run(); err != nil {
fmt.Println(err)
return
}
}
启动
go run main.go
访问
http://localhost:8080/router2/hello
至此我们支持了多个路由文件,并且使用路由组避免了同路径路由注册失败的问题
路由拆分到不同平台
上面我们已经支持了多个文件,并且支持路由分组,但是有时候项目规模实在太大,比如:
我们需要拆分成:
- web:web访问的路由
- app:app访问的路由
- common: 公共的基础路由,web和app都可以访问
上面这种在项目体量大的时候,还是很常见的,那在Gin 中该怎么写
目录结构
│ go.mod
│ go.sum
│ main.go
├─app
│ router.go
├─common
│ router.go
├─routers
│ routers.go
└─web
router.go
文件:main.go
package main
import (
"fmt"
// 引入自定义路由模块
app "gin_test/app"
common "gin_test/common"
routers "gin_test/routers"
web "gin_test/web"
)
func main() {
// 加载所有模块的路由配置
routers.Include(app.Routers, web.Routers, common.Routers)
// 初始化路由
router := routers.Init()
// 启动监听并打印错误
if err := router.Run(); err != nil {
fmt.Println(err)
return
}
}
文件:routers/routers.go
package routers
import (
"github.com/gin-gonic/gin"
)
// 定义单个路由model
type RouterModel func(router *gin.Engine)
// 路由model 切片
var routerModels = make([]RouterModel, 0)
// 注册路由model配置
func Include(models ...RouterModel) {
// 塞到路由模块切片中
routerModels = append(routerModels, models...)
}
// 初始化路由
func Init() *gin.Engine {
router := gin.Default()
for _, model := range routerModels {
model(router)
}
return router
}
文件:web/router.go
package gin_test
import "github.com/gin-gonic/gin"
// 控制器方法
func hello(context *gin.Context) {
context.JSON(200, "这是 Web 模块")
}
// 设置路由
func Routers(router *gin.Engine) {
// 设置路由组
Web := router.Group("/Web")
{
// 注册路由
Web.GET("/hello", hello)
}
}
文件:app/router.go
package gin_test
import "github.com/gin-gonic/gin"
// 控制器方法
func hello(context *gin.Context) {
context.JSON(200, "这是app模块")
}
// 设置路由
func Routers(router *gin.Engine) {
// 设置路由组
App := router.Group("/App")
{
// 注册路由
App.GET("/hello", hello)
}
}
文件:common/router.go
package gin_test
import "github.com/gin-gonic/gin"
// 控制器方法
func hello(context *gin.Context) {
context.JSON(200, "这是 Common 模块")
}
// 设置路由
func Routers(router *gin.Engine) {
// 设置路由组
Common := router.Group("/Common")
{
// 注册路由
Common.GET("/hello", hello)
}
}
启动
go run main.go
路由
请求
http://localhost:8080/App/hello
代码
这个demo 代码我放在了这里:
https://gitee.com/makalochen/go-test/tree/master/gin_test
结语
其他什么参数获取,上传文件,自定义验证啥,在官方文档都可以找到,我就不写了,我只能说写的再好也没官方给的标准
官网中文文档地址: