簡介
中文官網: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
結語
其他什麼參數獲取,上傳文件,自定義驗證啥,在官方文檔都可以找到,我就不寫了,我只能說寫的再好也沒官方給的標準
官網中文文檔地址: