Hertz|青训营笔记

78 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 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路由

提供了 GETPOSTPUTDELETEANY 等方法用于注册路由。

//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文档