写点什么

Go 语言快速入门指南:GET 和 POST 方法

作者:宇宙之一粟
  • 2023-04-24
    中国香港
  • 本文字数:3202 字

    阅读完需:约 11 分钟

Go 语言快速入门指南:GET 和 POST 方法

介绍

超文本传输协议(HTTP)客户端用于建立连接并向 HTTP 服务器请求数据。最常见的方法是 GETPOST


在 Go 中,我们使用 http 来创建 GET 和 POST 请求。该包提供 HTTP 客户端和服务器实现。


http 包支持 RFC 2616 中定义的属性,如超时、重定向和 cookies。虽然这个包有更多的基本方法,比如http.Client.Get()http.Client.Post() 方法,但为了应用自定义头信息,http.NewRequest() 函数可以和 http.Client.Do() 方法一起使用。本章演示了 GETPOST 请求,通过使用更常见的功能的例子,如客户端超时、cookies 和自定义头信息。


GET 请求

HTTP GET 方法请求指定资源的表示,使用 GET 的请求应该只检索数据。一个简单的 GET 请求可以用 http.Client.Get() 方法完成:


package main
import ( "fmt" "io/ioutil" "log" "net/http")
func main() { resp, err := http.Get("https://www.baidu.com") if err != nil { log.Fatal(err) }
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) }
fmt.Println(string(body))}
复制代码


main 函数中,它向 www.baidu.com 发送了一个 GET 请求,并从响应中读取了响应体。如果在发送请求或读取响应体的过程中出现错误,程序将会调用 log.Fatal 函数打印错误信息并退出。


io.ReadAll() 函数将整个响应主体读入一个字节片中。然后,您可以将字节切片转换为字符串并将其打印出来。


最后,程序将响应体转换成字符串并打印到控制台上。



如果需要自定义头信息,可以使用 http.NewRequest() 函数和 http.Client.Do() 方法的组合。


req, err := http.NewRequest("GET", "http://www.baidu.com/", nil)if err != nil {    // handle error}req.Header.Set("User-Agent", "MyUserAgent/1.0")
复制代码


http.NewRequest 函数采用三个参数:HTTP 方法、URL 和请求正文。在此示例中,我们正在创建一个没有请求正文的 GET 请求。


然后,您可以使用 *http.Request 对象的 Header 字段为请求设置标头。在此示例中,我们正在设置 User-Agent 标头。


package main
import ( "fmt" "io/ioutil" "log" "net/http")
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://www.baidu.com", nil)
if err != nil { log.Println(err) return }
req.Header.Add("If-None-Match", `W/"wyzzy"`) resp, err := client.Do(req) if err != nil { log.Println(err) return }
defer resp.Body.Close() recv, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) return }
fmt.Printf("%s", recv)}
复制代码


运行 go run main.go,输出结果:



自定义 Header


req.Header.Add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0)")
复制代码


POST 请求


Go 语言中的 http.NewRequest 函数创建一个 HTTP POST 请求,其中第一个参数是 HTTP 请求方法,第二个参数是 POST 请求的 URL(在此例中为 www.baidu.com),第三个参数是请求数据(JSON 数据)。此外,还设置了 HTTP 请求头 Content-Type 为 application/json。最后,创建一个客户端并使用 client.Do(request) 方法进行 POST 请求。


要发送请求,您可以使用 http.DefaultClient.Do 函数:


resp, err := http.DefaultClient.Do(req)if err != nil {    // handle error}defer resp.Body.Close()
复制代码


在 REST API 中,GET 请求仅用于从服务器检索信息,因此为了使程序完全参与 REST API,程序还需要支持发送 POST 请求。POST 请求几乎是 GET 请求的相反,客户端在请求正文中向服务器发送数据。为了实现这一点,需要更新程序,将请求发送为 POST 请求,包括请求正文,并更新服务器以打印有关客户端请求的更多信息。


package main
import ( "bytes" "encoding/json" "fmt" "io/ioutil" "log" "net/http")
func main() { values := map[string]string{"foo": "baz"} jsonData, err := json.Marshal(values)
req, err := http.NewRequest(http.MethodPost, "https://httpbin.org/post", bytes.NewBuffer(jsonData)) if err != nil { log.Fatal(err) }
// appending to existing query args q := req.URL.Query() q.Add("foo", "bar")
// assign encoded query string to http request req.URL.RawQuery = q.Encode()
client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Errored when sending request to the server") return }
defer resp.Body.Close() responseBody, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) }
fmt.Println(resp.Status) fmt.Println(string(responseBody))}
复制代码


在这个例子中,方法、URL 和正文是用 http.NewRequest() 函数设置的,以便接收一个 http.Request 对象。然后,用 http.Request.Header.Set()方法设置一个头,使用标准键值对作为输入。接下来,在 http.Client结构中初始化 Timeout 字段,并返回一个新的 http.Client 对象。现在,GET 请求是用 URL 建立的,客户端头也被定义了,它们与自定义超时一起被用于

和自定义超时来发送和接收 HTTP 请求,使用 http.Client.Do() 方法发送和接收 HTTP 请求。最后,响应对象被从 最后,从 http.Client.Do() 方法中接收响应对象,并在打印响应之前关闭请求体响应。


HTTP POST 方法向服务器发送数据。它通常在上传文件或提交一个完整的网络表格时使用。

HTTP 1.1 协议支持 HTTP 持久连接,也称为 HTTP Keep-Alive。这允许客户端和服务器在发送多个 HTTP 请求/响应时重用相同的基础 TCP 连接。因此,客户端不是为每个 HTTP 请求建立连接,而是重复使用先前创建的 TCP 连接。这在性能方面特别有用,当向同一主机发送多个请求时尤其如此。


在整个代码库中重复使用 http.Client。它的一个例子如下:


package main
import ( "bytes" "io/ioutil" "log" "net/http" "time")
func httpClient() *http.Client { client := &http.Client{Timeout: 10 * time.Second} return client}
func sendRequest(client *http.Client, method string) []byte { endpoint := "https://httpbin.org/post" values := map[string]string{"foo": "baz"} jsonData, err := json.Marshal(values)
req, err := http.NewRequest(method, endpoint, bytes.NewBuffer(jsonData)) if err != nil { log.Fatalf("Error Occurred. %+v", err) }
response, err := client.Do(req) if err != nil { log.Fatalf("Error sending request to API endpoint. %+v", err) }
// Close the connection to reuse it defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body) if err != nil { log.Fatalf("Couldn't parse response body. %+v", err) }
return body}
func main() { // c should be re-used for further calls c := httpClient() response := sendRequest(c, http.MethodPost) log.Println("Response Body:", string(response))}
复制代码


总结

net/http 包向该服务器发出 HTTP 请求。首先,您使用 http.Get 函数通过 Go 的默认 HTTP 客户端向服务器发出 GET 请求。然后,您使用 http.NewRequesthttp.DefaultClientDo() 方法发出 GET 请求。


最后,您在 http.Request 的 Header 字段上使用了 Set 方法来设置请求的 Content-Type 标头,并通过创建您自己的 HTTP 客户端而不是使用 Go 的默认客户端来设置请求持续时间的 30 秒超时。 net/http 包不仅仅包含您在本教程中使用的功能。它还包含一个 http.Post 函数,可用于发出 POST 请求,类似于 http.Get 函数。该软件包还支持保存和检索 cookie 等功能。


参考链接:

发布于: 刚刚阅读数: 6
用户头像

宇宙古今无有穷期,一生不过须臾,当思奋争 2020-05-07 加入

🏆InfoQ写作平台-签约作者 🏆 混迹于江湖,江湖却没有我的影子 热爱技术,专注于后端全栈,轻易不换岗 拒绝内卷,工作于外企开发,弹性不加班 热衷分享,执着于阅读写作,佛系不水文 同名公众号:《宇宙之一粟》

评论

发布
暂无评论
Go 语言快速入门指南:GET 和 POST 方法_Go_宇宙之一粟_InfoQ写作社区