Go Web框架——Hertz基础教程| 青训营笔记

2,680 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天

前言

本文主要内容为Go语言HTTP框架——Hertz

Hertz是字节内部开源的http框架,参考了其他开源框架的优势,结合字节跳动内部的需求,具有高易用性、高性能、高扩展性等特点。

基础使用

安装Hertz

安装Hertz需要确保电脑已经正确安装了Go,并且Go的版本要>=1.15

执行以下命令进行安装Hertz

go install github.com/cloudwego/hertz/cmd/hz@latest

安装后进行验证,输入以下命令:

hz -v

如果能正确输出版本信息,如下,就说明已经安装好了。

hz version v0.5.2

生成示例代码

可以使用hz命令直接生成示例代码,步骤如下:

  1. 在当前目录下创建 hertz 文件夹,进入该目录中
  2. 执行生成代码命令 hz new 或者使用hz new -module example
  3. 执行命名go mod tidy 整理、拉取依赖

生成代码目录如下:

image.png

打开main.go文件,添加以下代码

image.png

到此,一个简单的http服务就完成了,现在可以编译并启动Server了。

go run main.go

运行命令,成功启动后,输出以下信息:

image.png

我们可以看到,服务已经正常启动,并且默认端口号为8888,打开浏览器输入访问地址

http://127.0.0.1:8888/ping

访问后,可以看到浏览器输出一个json,内容如下:

{"message":"pong"}

Hertz路由

Hertz提供了多种路由规则,路由的优先级为:静态路由 > 命名路由 > 通配路由。

静态路由

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

image.png

路由组

Hertz提供了路由组(Group)的能力,用于支持路由分组的功能。

image.png

参数路由

Hertz 支持使用 :name 这样的命名参数设置路由,并且命名参数只匹配单个路径段。

如果我们设置/hertz/:version路由,匹配情况如下:

路径是否匹配
/hertz/v1匹配
/hertz/v2匹配
/hertz/v1/detail不匹配
/hertz/不匹配

通过使用 RequestContext.Param 方法,我们可以获取路由中携带的参数。

h.GET("/hertz/:version", func(ctx context.Context, c *app.RequestContext) {
    version := c.Param("version")
    c.String(consts.StatusOK, "Hello %s", version)
})

通配路由

Hertz 支持使用 *path 这样的通配参数设置路由,并且通配参数会匹配所有内容。

如果我们设置/hertz/*path路由,匹配情况如下

路径是否匹配
/hertz/v1匹配
/hertz/v1/detail匹配
/hertz/匹配

通过使用 RequestContext.Param 方法,我们可以获取路由中携带的参数。

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提供了 BindValidateBindAndValidate 函数用于进行参数绑定校验。

绑定的作用是把http请求的参数封装到定义的结构体里面方便开发使用,Hertz使用的是tag的方式进行绑定的。

Tag说明
path绑定 url 上的路径参数,相当于 hertz 路由 :param*param 中拿到的参数
form绑定请求的 body 内容
query绑定请求的 query 参数
header绑定请求的 header 参数
json绑定 json 参数
vd参数校验

绑定使用的是BindAndValidate方法,使用方法如下:

image.png

Hertz Client

Hertz提供了 Http Client 用于帮助用户发送 Http 请求,可以在代码的逻辑中请求第三方服务。

例如,使用GET发送一个Http请求:

func Get() {
    c, err := client.NewClient()
    if err != nil {
        return
    }
    status, body, _ := c.Get(context.Background(), nil, "http://www.example.com")
    fmt.Printf("status=%v body=%v\n", status, string(body))
}

使用POST发送一个Http请求:

func Post() {
    c, err := client.NewClient()
    if err != nil {
        return
    }

    var postArgs protocol.Args
    postArgs.Set("arg", "a") // 发送参数
    status, body, _ := c.Post(context.Background(), nil, "http://www.example.com", &postArgs)
    fmt.Printf("status=%v body=%v\n", status, string(body))
}

代码生成

Hertz提供了代码生成工具 HzhzHertz 框架提供的一个用于生成代码的命令行工具,hz 可以基于 thriftprotobufIDL 生成 Hertz 项目的脚手架。

先定义一个IDL文件,如hello.thrift

namespace go hello.example

struct HelloReq {
    // 添加 api 注解为方便进行参数绑定
    1: string Name (api.query="name"); 
}
struct HelloResp {
    1: string RespBody;
}

service HelloService {
    HelloResp HelloMethod(1: HelloReq request) (api.get="/hello");
}

执行命令生成代码,并整理依赖:

hz new -idl hello.thrift
go mod tidy

生成的文件结构如下:

image.png

Hertz性能

Hertz是一个高性能Web框架,之所以高性能是因为以下几点:

  • 使用高性能网络库Netpoll
  • Json编解码SonicSonic是一个高性能Json编解码库
  • 使用sync.Pool复用对象协议层数据解析优化

Hertz生态

Hertz拥有非常丰富的扩展生态:

  • Http2扩展
  • opentelemetry扩展
  • 国际化扩展
  • 反向代理扩展
  • JWT鉴权扩展
  • Websocket扩展
  • 丰富的代码示例

引用

字节内部视频——Go框架三件套详解(Web/RPC/ORM)

CloudWeGo Hertz文档