1. http.Transport简介
http.Transport是Go语言中一个用于发送http请求的结构体。在go1.7版本之前,默认的http.Client使用一个全局的http.Transport,而从go1.7版本开始,http.Client会在每个请求中使用新的http.Transport。对于需要设置复杂的http请求参数,如控制代理,设置TLS选项或更改默认的重试机制等,可以直接使用http.Transport结构体。
2. 请求编码技巧
2.1 URL编码
在发送GET请求时,需要将请求参数进行URL编码以保证特殊字符不会影响请求的解析。对于Go语言中的http包,提供了Url.QueryEscape()函数来进行URL编码。
import (
"net/url"
"fmt"
)
func main() {
value := "123@ab#&"
result := url.QueryEscape(value)
fmt.Println(result)
}
运行代码后,会得到如下结果:
输出:
// Output:
// 123%40ab%23%26
2.2 JSON编码
由于JSON成为了比XML更流行的数据传输格式,所以很多API都支持接收或返回JSON数据。在Go语言中,可以使用json.Marshal()对结构体进行JSON编码,使用json.Unmarshal()对JSON字符串进行解码。下面是一个用于POST请求发送JSON数据的例子:
import (
"bytes"
"encoding/json"
"net/http"
)
type Data struct {
Name string `json:"name"`
Value int `json:"value"`
}
func main() {
url := "http://example.com/api/data"
data := &Data{
Name: "test",
Value: 123,
}
body, err := json.Marshal(data)
if err != nil {
panic(err)
}
req, err := http.NewRequest("POST", url, bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
// 处理返回的数据
}
上面的代码中,首先定义了一个Data结构体,然后使用json.Marshal()函数将Data类型的变量data编码成JSON字符串,接着使用http.NewRequest()函数创建一个POST请求,并将JSON字符串作为请求体。最后,在发出请求时需要设置请求的Content-Type为application/json。当然,需要注意的是JSON格式的响应体需要用json.Unmarshal()函数进行解码。
3. 响应解码技巧
3.1 JSON解码
与请求编码类似,响应解码也需要根据返回的数据类型进行不同的处理。对于返回的JSON数据,可以使用json.Unmarshal()函数将JSON字符串解码成对应的Go语言结构体。
import (
"encoding/json"
"net/http"
"io/ioutil"
)
type Result struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
Name string `json:"name"`
Value int `json:"value"`
} `json:"data"`
}
func main() {
url := "http://example.com/api/result"
client := &http.Client{}
res, err := client.Get(url)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
result := &Result{}
err = json.Unmarshal(body, result)
if err != nil {
panic(err)
}
// 处理响应数据
}
上面的代码中,首先使用http.Client的Get方法获取响应体,然后使用ioutil.ReadAll()将响应体中的数据读取到内存中。接着使用json.Unmarshal()将响应数据解码成对应的Result结构体。
3.2 XML解码
如果是接收到XML格式的响应数据,就需要使用Go语言中的encoding/xml库。首先需要定义一个可用于解码XML的结构体,并在每个字段上使用标记来指定如何解析XML数据。
import (
"encoding/xml"
"net/http"
"io/ioutil"
)
type Data struct {
Name string `xml:"name"`
Value int `xml:"value"`
}
type Result struct {
Code int `xml:"code"`
Msg string `xml:"msg"`
Data Data `xml:"data"`
}
func main() {
url := "http://example.com/api/result.xml"
client := &http.Client{}
res, err := client.Get(url)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
result := &Result{}
err = xml.Unmarshal(body, result)
if err != nil {
panic(err)
}
// 处理响应数据
}
上面的代码中,首先定义了一个Data结构体和一个可用于解码XML的Result结构体。在Data结构体的每个字段上使用xml标记来指定如何解析XML数据,在Result结构体中使用Data结构体来表示data元素。
4. 实际应用
http.Transport结构体不仅仅是一个发送http请求的工具,它还可以用于控制http连接的复用、超时和代理等。下面是一个使用http.Transport结构体发送GET请求的例子,其中控制了http连接的复用和设置了请求超时。
import (
"net/http"
"time"
)
func main() {
url := "http://example.com/api/data"
transport := &http.Transport{
MaxIdleConns: 10, // 连接池最大闲置连接数
IdleConnTimeout: 30 * time.Second, // 闲置连接超时时间
}
client := &http.Client{
Transport: transport,
Timeout: 30 * time.Second, // 请求超时时间
}
res, err := client.Get(url)
if err != nil {
panic(err)
}
defer res.Body.Close()
// 处理响应数据
}
上面的代码中,首先创建了一个http.Transport结构体,并设置了最大的连接闲置数和闲置连接超时。接着创建了一个http.Client结构体,并将上述http.Transport结构体作为其Transport属性的值,并设置了请求超时时间。最后使用client.Get()方法发送GET请求,并处理响应数据。
总结
本文介绍了使用http.Transport结构体发送http请求时,对请求参数进行编码和对响应数据进行解码的技巧。我们了解了如何通过URL编码和JSON编码来发送POST请求,并使用json.Unmarshal()和xml.Unmarshal()函数对JSON和XML格式的响应数据进行解码。最后,我们还给出了一个关于http.Transport的实际应用例子,控制http连接的复用和设置请求超时。