试试这样用Go发送HTTP请求

1,455 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

  1. 你是否用Go发送Http请求的时候在为API的繁琐而抓狂?
  2. 你是在用GO发送POST请求时参数杂乱无章而烦恼?
  3. 你是否用GO在构建表单请求上传文件而感到崩溃?
  4. 你是否用GO担心发送的请求并不是你想要的而感到困惑?
  5. 你是否用GO发送带路径参数的请求拼接参数时感到麻烦? 如果你有上面两条以上的烦恼,建议小伙伴认证看完restgo是怎么构建优雅的发送HTTP请求的。

restgo的愿景是编程人员不用关注怎么发送HTTP请求,而是通过傻瓜式,点,点,点,就可以轻松构建一个http请求。

安装restgo

go get github.com/xiao-ren-wu/restgo

先来个简单的,构建一个GET请求

func TestGet(t *testing.T) {
	resp, err := restgo.NewHttpBuilder().Send(restgo.GET, "http://www.baidu.com")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(resp.BodyStr())
}

可以看出只需要一行,就可以发送一个GET请求。代码非常简洁。 返回值是一个respWrapper和一个error

  • 用户可以通过BodyStr获取响应体的string格式,
  • Body获取响应的[]byte格式,
  • 通过BodyUnmarshal将body序列化成go的结构体,
  • 以及通过Header方法获取响应头信息

请求生成Curl

restgo提供生成Curl的功能,用户可以通过该功能获取最终发送的curl

生成Curl的函数签名如下

func (builder *httpBuilder) Curl(curlConsumer func(curl string)) *httpBuilder {
	builder.curlConsumerFunc = curlConsumer
	return builder
}

需要传入一个函数,函数的入参是curl字符串,restgo提供了默认控制台打印curl的函数

var ConsolePrint = func(curl string) {
	fmt.Println(curl)
}

可以使用默认的控制台打印

func TestGet(t *testing.T) {
	resp, err := restgo.NewHttpBuilder().
		Curl(restgo.ConsolePrint).
		Send(restgo.GET, "http://restgo.example.com")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(resp.BodyStr())
}

程序运行后,控制台打印curl信息

curl --location --request GET 'http://www.baidu.com' 

url拼接参数

假设获取用户信息需要传入id,并通过路径拼接的形式

func Test(t *testing.T) {
	resp, err := restgo.NewHttpBuilder().
		Query(map[string]string{
			"id": "1234",
		}).
		Send(restgo.GET, "http://restgo.example.com")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(resp.BodyStr())
}

路径参数

假设可以通过username获取用户信息,并在通过路径拼接的形式

func Test(t *testing.T) {
	resp, err := restgo.NewHttpBuilder().
		PathVariable(map[string]string{
			"name": "1234",
		}).
		Send(restgo.GET, "http://restgo.example.com/:name/detail")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(resp.BodyStr())
}

设置请求头信息

假设请求接口需要传入token认证

func Test(t *testing.T) {
	resp, err := restgo.NewHttpBuilder().
		Headers(map[string]string{
			"token": "xxxx",
		}).
		Send(restgo.GET, "http://restgo.example.com")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(resp.BodyStr())
}

发送POST请求

表单请求

默认POST请求是application/json形式,如果发送POST请求,需要指定Content-Type,目前支持multipart/form-dataapplication/x-www-form-urlencoded

func Test(t *testing.T) {
	resp, err := restgo.NewHttpBuilder().
		ContentType(restgo.FormData).
		Payload(map[string]string{
			"name": "1234",
		}).
		Send(restgo.GET, "http://restgo.example.com")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(resp.BodyStr())
}

试试上传文件

restgo支持单个文件上传,文件上传的路径可以是一个本地目录路径或者是一个文件的url地址

func Test(t *testing.T) {
	resp, err := restgo.NewHttpBuilder().
		ContentType(restgo.FormData).
		File("file", "/usr/local/test.image").
		Payload(map[string]string{
			"name": "1234",
		}).
		Send(restgo.GET, "http://restgo.example.com")
	if err != nil {
		t.Fatal(err)
	}
	t.Log(resp.BodyStr())
}

请求携带json的payload

Payload的方法入参是一个interface{}类型,这意味着我们可以传任意值,如果需要将body序列化成json格式,我们只需要指定Content-Typeapplication/json

// Payload 请求载荷,根据设置的Content-Type确定最终发送形式
func (builder *httpBuilder) Payload(body interface{}) *httpBuilder {
	builder.body = body
	return builder
}

body中携带二进制信息

有一些场景,需要在传输的body中携带二进制信息,比如大文件的分片上传,这时候,我们只需要在Payload方法中传入[]byte,然后通过指定Content-TypeOctetStream就可以了

下载文件到本地

有时候,我们想将一些图片或者视频等链接的内容下载到本地,通过restgo我们只需要调用resp的WriteFile就可以啦

func (wrapper *respWrapper) WriteFile(path string) error

WriteFile的入参是需要将文件保存的路径,如果该路径不存在,restgo会自动帮我们创建这个路径,然后保存文件。

好啦~关于restgo的使用就全部介绍完毕啦,有了restgo,相信读者可以很快的构建出想要的HTTP请求,

restgo的github地址是: github.com/xiao-ren-wu…

如果restgo对您的学习或者工作有帮助的话,请帮忙点个star~