这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
什么是Hertz?
Hertz是一个Golang微服务HTTP框架,它参考了gin、fasthttp、echo的优势,结合了字节跳动内部需求,使其具有高易用性、高性能、高扩展性等特点。
安装
需要go版本在1.15及以上,使用命令行工具
go install github.com/cloudwego/hertz/cmd/hz@latest
判断是否安装成功,使用以下命令:
hz -v
对应输出hertz的相应版本
hz version v0.5.1
Hertz基本使用
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
//初始化hertz对象,设置监听端口
h := server.Default(server.WithHostPorts("127.0.0.1:8080"))
//注册路由
//使用两个上下文1.传递原信息2.请求处理
h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, utils.H{"msg": "hello"})
})
h.Spin() //开启
}
Hertz路由
提供了 GET、POST、PUT、DELETE、ANY 等方法用于注册路由。
//get方法
h.GET("/get", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, "hello get!")
})
//post方法
h.POST("/post", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, "hello,post")
})
//put方法
h.PUT("/put", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, "hello,put")
})
//delete方法
h.DELETE("/delete", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, "hello,delete")
})
//head方法
h.HEAD("/head", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, "hello,head")
})
//用于所有方法
h.Any("/any", func(c context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, "hello,any")
})
Hertz 提供了路由组( Group )的能力,用于支持路由分组的功能,同时中间件也可以注册到路由组上。
v1 := h.Group("/v1")
v1.GET("/get", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "get")
})
v1.POST("/post", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "post")
})
Hertz 提供了参数路由、通配路由,其中关系是静态路由>命名路由>通配路由
//参数路由
//可以是/hertz/version、/hertz/you,但于/hertz/、/hertz/p/s不匹配
h.GET("/hertz/:version", func(ctx context.Context, c *app.RequestContext) {
version := c.Param("version")
c.String(consts.StatusOK, "Hello %s", version)
})
//通配路由
//使用 *action 这样的通配参数设置路由,并且通配参数会匹配所有内容
h.GET("/hertz/:version/*action", func(ctx context.Context, c *app.RequestContext) {
version := c.Param("version")
action := c.Param("action")
message := version + " is " + action
c.String(consts.StatusOK, message)
})
Hertz 参数绑定
提供BindAndValidate、Bind、Validate函数用于参数绑定和校验
// BindAndValidate
var req Test
err := ctx.BindAndValidate(&req)
// Bind
req = Test{}
err = ctx.Bind(&req)
// Validate,需要使用 "vd" tag
err = ctx.Validate(&req)
支持tag参数绑定,例如:
type se struct {
Path string `path:path` //绑定url上的路径
Query string `query:query` //绑定query请求
Form string `form:form` //绑定body上的请求内容
Json string `json:"json"` //绑定 json 参数
}
Hertz中间件
服务端中间件
Hertz 服务端中间件是 HTTP 请求-响应周期中的一个函数,提供了一种方便的机制来检查和过滤进入应用程序的 HTTP 请求。
// 方式一
//在请求到达业务逻辑之前执行,比如执行身份认证和权限认证
func MyMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
// pre-handle
// ...
c.Next(ctx) //向下执行
}
}
// 方式二
//在执行过业务逻辑之后执行,比如记录响应时间和从异常中恢复
func MyMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
c.Next(ctx) // call the next middleware(handler)
// post-handle
// ...
}
}
如果想快速终止中间件调用,可以使用以下方法,需要此时中间件仍在执行:
Abort():终止后续调用AbortWithMsg(msg string, statusCode int):终止后续调用,并设置 response中body,和状态码AbortWithStatus(code int):终止后续调用,并设置状态码
客户端中间件
客户端中间件实现和服务端中间件不同。Client 侧无法拿到中间件 index 实现递增,因此 Client 中间件采用提前构建嵌套函数的形式实现:
return func(ctx context.Context, req *protocol.Request, resp *protocol.Response) (err error) {
// pre-handle
// ...
err = next(ctx, req, resp)
if err != nil {
return
}
// post-handle
// ...
}
}
具体内容可以参考:Hertz文档