gin框架简介
构建web api接口一般用到http框架, golang的常用http框架有gin、Beego、Buffalo、Echo、Hertz等。使用http框架可以很方便向用户开放自己的api接口。 gin 的特性:
快速
基于 Radix 树的路由,小内存占用。没有反射。可预测的 API 性能。
支持中间件
传入的 HTTP 请求可以由一系列中间件和最终操作来处理。 例如:Logger,Authorization,GZIP,最终操作 DB。
Crash 处理
Gin 可以 catch 一个发生在 HTTP 请求中的 panic 并 recover 它。这样,你的服务器将始终可用。例如,你可以向 Sentry 报告这个 panic!
JSON 验证
Gin 可以解析并验证请求的 JSON,例如检查所需值的存在。
路由组
更好地组织路由。是否需要授权,不同的 API 版本…… 此外,这些组可以无限制地嵌套而不会降低性能。
错误管理
Gin 提供了一种方便的方法来收集 HTTP 请求期间发生的所有错误。最终,中间件可以将它们写入日志文件,数据库并通过网络发送。
内置渲染
Gin 为 JSON,XML 和 HTML 渲染提供了易于使用的 API。
可扩展性
新建一个中间件非常简单,去查看示例代码吧。
gin 框架快速使用
下载安装:
$ go get -u github.com/gin-gonic/gin
引入代码
import "github.com/gin-gonic/gin"
获取router
r := gin.Default()
得到router之后可以注册路由
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
启动服务:
r.Run() // 监听并在 0.0.0.0:8080 上启动服务
gin 框架中间件扩展
框架通过use方法设置中间件
// Use attaches a global middleware to the router. ie. the middleware attached though Use() will be
// included in the handlers chain for every single request. Even 404, 405, static files...
// For example, this is the right place for a logger or error management middleware.
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
engine.RouterGroup.Use(middleware...)
engine.rebuild404Handlers()
engine.rebuild405Handlers()
return engine
}
扩展中间件需要实现HandlerFunc接口
jwt认证
gin框架可以很方便使用中间件完成JWT认证
使用第三方库
go get -u github.com/gin-gonic/gin go get -u github.com/dgrijalva/jwt-go
使用示例:
package main
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/dgrijalva/jwt-go"
)
var (
jwtSecret = []byte("your-secret-key") // 用于生成和验证JWT的密钥
)
// 创建一个JWT
func createToken(userId int) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"userId": userId,
"exp": time.Now().Add(time.Hour * 24).Unix(), // 设置过期时间为一天
})
tokenString, err := token.SignedString(jwtSecret)
return tokenString, err
}
// JWT中间件
func authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
tokenString := c.GetHeader("Authorization")
if tokenString == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
c.Abort()
return
}
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil
})
if err != nil || !token.Valid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
c.Abort()
return
}
c.Next()
}
}
func main() {
r := gin.Default()
// 登录路由,生成JWT并返回给客户端
r.POST("/login", func(c *gin.Context) {
userId := 123 // 这里应该是从数据库或其他地方获取的用户ID
token, err := createToken(userId)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create token"})
return
}
c.JSON(http.StatusOK, gin.H{"token": token})
})
// 受保护的路由,需要通过JWT验证
r.GET("/protected", authMiddleware(), func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Access granted"})
})
r.Run(":8080")
}