go工具库:hertz api框架 hertz client的使用

介绍

Hertz 是 字节跳动(ByteDance)开源的高性能 Golang 微服务框架,用于构建 Web 服务,特别适合对性能要求极高的场景。

基于字节内部自研的网络库 netpoll,具备极低的延迟和高并发能力。

对比标准库 net/http,在 QPS、RT、内存占用等指标上表现更优秀。

灵活易用

支持中间件机制,兼容 Gin 风格。

可插拔的组件设计,便于自定义协议栈、序列化方式、拦截器等。

支持自动路由注册(借助 IDL 工具)。

全面功能

路由、请求解析、响应封装

自动生成 HTTP 服务代码(结合 Kitex 使用)

内建 metrics、pprof、tracing、限流、熔断、超时等能力

多种序列化支持:JSON、Protobuf、Thrift、MsgPack 等

微服务友好

适配 CloudWeGo 微服务生态,和 Kitex 天然集成。

支持服务注册、发现、链路追踪等。

一个示例:

go 复制代码
package main

import (
    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
)

func main() {
    h := server.Default()

    h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
        ctx.JSON(200, map[string]string{
            "message": "pong",
        })
    })

    h.Spin()
}

创建client

创建一个标准的client

纯净的golang http client,sdk 一般用这个

go 复制代码
package main


func main() {
   c, err := client.NewClient()
   // your code after this
}

使用配置创建标准的client

go 复制代码
package main

import (
   "time"

)

func main() {
   c, err := client.NewClient(client.WithDialTimeout(1 * time.Second))
   //your code after this
}

支持的配置项

Hertz Client 配置表

配置名称 类型 说明
WithDialTimeout time.Duration 建立连接超时时间,默认值:1000ms
WithMaxConnsPerHost int 单个 ip:port 的最大连接数,默认 512
WithMaxIdleConnDuration time.Duration 长连接的最大空闲时间,默认 10s
WithMaxConnDuration time.Duration 长连接的最大存在时间,默认无限
WithMaxConnWaitTimeout time.Duration 最大等待连接时长,默认不等待
WithKeepAlive bool 设置是否使用长连接,默认为 true
WithMaxIdemponentCallAttempts int 幂等调用的最大尝试次数,默认为 5 (内部版本 < 1.7.0,外部版本 < 0.4.0)
WithClientReadTimeout time.Duration 读取 response 的最长时间,默认无限
WithWriteTimeout time.Duration 写超时,默认无限(外部版本 > v1.7.0)
WithDialer(standard.NewDialer()) network.Dialer 底层网络库 dialer,默认 netpoll.NewDialer()。设置为 standard.NewDialer() 会使用 Golang 原生 dialer。 ⚠️ Netpoll 不支持 TLS,因此使用 TLS 时需切换到标准库
WithTLSConfig *tls.Config 用于发送 HTTPS 请求,设置该配置会自动将 dialer 切换为标准库
WithResponseBodyStream bool 是否使用流式读取 response body
WithRetryConfig ...retry.Option 设置 Client 的 retry 配置 (内部版本 >= 1.7.0,外部版本 >= 0.4.0)
WithRequestTimeout time.Duration 设置请求超时。注意Do 方法搭配此选项不会与 mesh 联动,mesh 默认超时为 4s,最终取较短者。如需联动应使用 DoTimeout / DoDeadline
WithDisablePathNormalizing bool 是否禁用 URL 归一化,默认开启归一化。设置为 true 可使用原始 URL 发送请求

使用配置创建byted client

go 复制代码
package main

import (
   "time"

)

func main() {
   c, err := byted.NewClient(byted.WithAppClientOptions(client.WithDialTimeout(1 * time.Second)))
}

支持的配置项

配置名称 类型 说明
WithAppClientOptions ...config.ClientOption 设置标准的 client 配置,详情见「Client API 示例」
WithEnableTracing bool 是否开启 trace,默认为 true
WithEnableSpanLog bool 是否为每次请求打印日志,默认为 true
WithEnableSpanMetrics bool 是否为每次请求打印 metrics,默认为 true
WithDumpRequest bool 是否在 trace span 上记录请求体和 URL 参数,默认为 false
WithSlowRequestThreshold time.Duration 如果请求时间超过该值,trace 将强制采样
WithLoadBalancer loadbalance.Loadbalancer 使用自定义负载均衡,详情见「服务发现 & 负载均衡」
WithDisableDefaultDiscovery bool 禁用默认服务发现中间件,详情见「服务发现 & 负载均衡」
WithHostPorts ...discovery.Instance 指定 client 访问的下游实例,详情见「服务发现 & 负载均衡」
WithToMethodTagDecider (类型未指定) 指定 client 上报 method tag 的方法

发起请求

  1. Do
    func (c *Client) Do(ctx context.Context,req *Request, resp Response) error
    Do会发送请求并将响应内容写入resp中,该函数不支持重定向跳转,如要使用,请使用DoRedirects或者Get
    方法
    package main
go 复制代码
import (
   "context"
   "fmt"

  
)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.SetMethod(consts.MethodGet)                            //设置请求方法
   req.Header.SetContentTypeBytes([]byte("application/json")) //设置请求header
   req.SetRequestURI("http://example.com")                    //设置请求url
   err = c.Do(context.Background(), req, res)
   if err != nil {
      return
   }
   fmt.Printf("%v", string(res.Body())) //读取响应body
}
  1. DoDeadline
    func (c *Client) DoDeadline(ctx context.Context,req *Request, resp Response, deadline time.Time) error
    DoDeadline会发送请求并将响应内容写入resp中,如果在给定截止日期(deadline)后没有响应则会返回github.com/cloudwego/hertz/pkg/common/errors 下的 error.ErrTimeout 错误。该方法不支持重定向跳转,如要使用,请使用DoRedirects或者Get
    方法
    该方法会和 Mesh 的超时联动
go 复制代码
package main

import (
   "context"
   "fmt"
   "time"


)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.SetMethod(consts.MethodGet)         //设置请求方法
   req.SetRequestURI("http://example.com") //设置请求url
   c.DoDeadline(context.Background(), req, res, time.Now().Add(1*time.Second))
   fmt.Printf("%v\n", string(res.Body()))
}
  1. DoRedirects
    func (c *Client) DoRedirects(ctx context.Context,req *Request, resp *Response, maxRedirectsCount int) error
    Hertz Client DoRedirects 接口预期外 404
    DoRedirects与Do的区别是它支持重定向跳转,当重定向次数超过maxRedirectsCount时会返回error
go 复制代码
package main

import (
   "context"
   "fmt"


)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.SetMethod(consts.MethodGet)                            //设置请求方法
   req.Header.SetContentTypeBytes([]byte("application/json")) //设置请求header
   req.SetRequestURI("http://example.com")                    //设置请求url
   err = c.DoRedirects(context.Background(), req, res, 1)
   if err != nil {
      return
   }
   fmt.Printf("%v\n", string(res.Body())) //读取响应body
}
  1. DoTimeout
    func (c *Client) DoTimeout(ctx context.Context,req *Request, resp Response, timeout time.Duration) error
    DoTimeout发送给定的请求并将响应内容写入resp中,如果在给定超时时间(timeout)后没有响应则会返回timeout错误。该方法不支持重定向跳转,如要使用,请使用DoRedirects或者Get
    方法
    该方法会和 Mesh 的超时联动,这个超时会传递给 mesh,以代码超时为准
go 复制代码
package main

import (
   "context"
   "fmt"
   "time"


)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.SetMethod(consts.MethodGet)                            //设置请求方法
   req.Header.SetContentTypeBytes([]byte("application/json")) //设置请求header
   req.SetRequestURI("http://example.com")                    //设置请求url
   err = c.DoTimeout(context.Background(), req, res, 1*time.Second)
   if err != nil {
      return
   }
   fmt.Printf("%v\n", string(res.Body())) //读取响应body
}
  1. Get
    func (c *Client) Get(ctx context.Context,dst []byte, url string) (statusCode int, body []byte, err error)
    Get会根据url返回相应的状态码和响应body;dst会被替换成响应body(响应的body会赋值给dst),如果dst太小会分配一个新的slice;该方法支持重定向跳转
go 复制代码
package main

import (
   "context"
   "fmt"

)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   status, body, _ := c.Get(context.Background(), nil, "http://google.com")
   fmt.Printf("status=%v body=%v\n", status, string(body))
}
  1. GetDeadline
    func (c *Client) GetDeadline(ctx context.Context,dst []byte, url string, deadline time.Time) (statusCode int, body []byte, err error)
    GetDeadline会根据url返回相应的状态码和响应body;如果在给定截止日期(deadline)后没有响应则会返回timeout错误,dst会被替换成响应请求body,如果dst太小会分配一个新的slice;该方法支持重定向跳转
go 复制代码
package main

import (
   "context"
   "fmt"
   "time"

)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   status, body, _ := c.GetDeadline(context.Background(), nil, "http://google.com", time.Now().Add(1*time.Second))
   fmt.Printf("status=%v body=%v\n", status, string(body))
}
  1. GetTimeout
    func (c *Client) GetTimeout(ctx context.Context,dst []byte, url string, timeout time.Duration) (statusCode int, body []byte, err error)
    GetTimeout会根据url返回相应的状态码和响应body;如果在给定超时时间(timeout)后没有响应则会返回hertz.ErrTimeout错误,dst会被替换成响应请求body,如果dst太小会分配一个新的slice;该方法支持重定向跳转
go 复制代码
package main

import (
   "context"
   "fmt"
   "time"

)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   status, body, _ := c.GetTimeout(context.Background(), nil, "http://google.com", 1*time.Second)
   fmt.Printf("status=%v body=%v\n", status, string(body))
}
  1. Post
    func (c *Client) Post(ctx context.Context,dst []byte, url string, postArgs *Args) (statusCode int, body []byte, err error)
    Post会根据url和post参数发送post请求,dst会被替换成响应请求body(响应的body会赋值给dst),如果dst太小会分配一个新的slice;该方法支持重定向跳转;使用的content-type是application/x-www-url-form
go 复制代码
package main

import (
   "context"
   "fmt"


)

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

   var postArgs protocol.Args
   postArgs.Set("arg", "a") //设置post请求参数
   status, body, _ := c.Post(context.Background(), nil, "http://google.com", &postArgs)
   fmt.Printf("status=%v body=%v\n", status, string(body))
}

发起multipart/form-data请求

go 复制代码
package main

import (
   "context"

  
)

func main() {
   client, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.Header.SetMethod(consts.MethodPost) //设置请求方法
   req.SetRequestURI("http://example.com") //设置请求url
   req.SetMultipartFormData(map[string]string{
      "msg": "test message",
   })
   err = client.Do(context.Background(), req, res)
   return
}
相关推荐
крон2 小时前
【Auto.js例程】华为备忘录导出到其他手机
开发语言·javascript·智能手机
zh_xuan2 小时前
c++ 单例模式
开发语言·c++·单例模式
老胖闲聊3 小时前
Python Copilot【代码辅助工具】 简介
开发语言·python·copilot
Blossom.1183 小时前
使用Python和Scikit-Learn实现机器学习模型调优
开发语言·人工智能·python·深度学习·目标检测·机器学习·scikit-learn
曹勖之3 小时前
基于ROS2,撰写python脚本,根据给定的舵-桨动力学模型实现动力学更新
开发语言·python·机器人·ros2
豆沙沙包?4 小时前
2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
java·开发语言·游戏
军训猫猫头4 小时前
96.如何使用C#实现串口发送? C#例子
开发语言·c#
liuyang-neu4 小时前
java内存模型JMM
java·开发语言
roman_日积跬步-终至千里5 小时前
【Go语言基础【14】】defer与异常处理(panic、recover)
golang
我很好我还能学6 小时前
【面试篇 9】c++生成可执行文件的四个步骤、悬挂指针、define和const区别、c++定义和声明、将引用作为返回值的好处、类的四个缺省函数
开发语言·c++