Go HTTP GET/POST 请求
最后修改时间 2024 年 4 月 11 日
在本文中,我们将展示如何在 Golang 中发送 HTTP GET 和 POST 请求。
HTTP
超文本传输协议(Hypertext Transfer Protocol (HTTP))是一种用于分布式、协作式、超媒体信息系统的应用层协议。HTTP 协议是万维网数据通信的基础。
在代码示例中,我们使用了 httpbin.org
,这是一个免费的 HTTP 请求和响应服务,以及 webcode.me
,这是一个用于测试的微型 HTML 页面。
HTTP GET
HTTP GET 方法请求指定资源的表示。使用 GET 的请求应该只检索数据。
HTTP POST
HTTP POST 方法将数据发送到服务器。它通常用于上传文件或提交完成的 Web 表单。
Go http
在 Go 中,我们使用 http
包来创建 GET 和 POST 请求。该包提供了 HTTP 客户端和服务器实现。
Go GET 请求
以下示例在 Go 中创建了一个简单的 GET 请求。
package main import ( "fmt" "io/ioutil" "log" "net/http" ) func main() { resp, err := http.Get("http://webcode.me") 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)) }
我们向 webcode.me
网页发出 GET 请求。
resp, err := http.Get("http://webcode.me")
使用 Get
函数发出 GET 请求。
if err != nil { log.Fatal(err) }
我们检查错误。
defer resp.Body.Close()
客户端完成使用后必须关闭响应体。
body, err := ioutil.ReadAll(resp.Body)
我们使用 ReadAll
读取响应体的内容。
fmt.Println(string(body))
我们将接收到的数据打印到控制台。
$ go run get_req.go <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My html page</title> </head> <body> <p> Today is a beautiful day. We go swimming and fishing. </p> <p> Hello there. How are you? </p> </body> </html>
除了 ioutil.ReadAll
,我们还可以使用 io.Copy
函数。
package main import ( "io" "log" "net/http" "os" ) func main() { resp, err := http.Get("http://webcode.me") if err != nil { log.Fatal(err) } defer resp.Body.Close() _, err = io.Copy(os.Stdout, resp.Body) if err != nil { log.Fatal(err) } }
io.Copy
函数从源复制到目标,直到源到达 EOF 或发生错误。它返回复制的字节数以及在复制过程中遇到的第一个错误(如果有)。
在下一个示例中,页面被写入一个文件。
package main import ( "log" "net/http" "os" ) func main() { r, err := http.Get("http://webcode.me") if err != nil { log.Fatal(err) } defer r.Body.Close() f, err := os.Create("index.html") if err != nil { log.Fatal(err) } defer f.Close() _, err = f.ReadFrom(r.Body) if err != nil { log.Fatal(err) } }
我们使用 os.Create
创建一个新文件,并使用 ReadFrom
将内容写入文件。
Go 异步请求
Go 有 goroutines 用于发出异步请求。goroutine 是由 Go 运行时管理的轻量级线程。
package main import ( "fmt" "io/ioutil" "log" "net/http" "regexp" "sync" ) func main() { urls := []string{ "http://webcode.me", "https://example.com", "http://httpbin.org", "https://perl.net.cn", "https://php.ac.cn", "https://pythonlang.cn", "https://vscode.js.cn", "https://clojure.net.cn", } var wg sync.WaitGroup for _, u := range urls { wg.Add(1) go func(url string) { defer wg.Done() content := doReq(url) title := getTitle(content) fmt.Println(title) }(u) } wg.Wait() } func doReq(url string) (content string) { resp, err := http.Get(url) defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) } return string(body) } func getTitle(content string) (title string) { re := regexp.MustCompile("<title>(.*)</title>") parts := re.FindStringSubmatch(content) if len(parts) > 0 { return parts[1] } else { return "no title" } }
我们发出多个异步 HTTP 请求。我们获取每个网页的 title
标签的内容。
var wg sync.WaitGroup
WaitGroups
用于管理 goroutines。它等待一组 goroutines 完成。
go func(url string) { defer wg.Done() content := doReq(url) title := getTitle(content) fmt.Println(title) }(u)
goroutine 使用 go
关键字创建。
$ go run async_req.go The Perl Programming Language - www.perl.org Welcome to Python.org Visual Studio Code - Code Editing. Redefined PHP: Hypertext Preprocessor Example Domain httpbin.org Clojure My html page
带查询参数的 Go GET 请求
以下示例将查询参数附加到 URL。
package main import ( "fmt" "io/ioutil" "log" "net/http" "net/url" ) func main() { name := "John Doe" occupation := "gardener" params := "name=" + url.QueryEscape(name) + "&" + "occupation=" + url.QueryEscape(occupation) path := fmt.Sprintf("https://httpbin.org/get?%s", params) resp, err := http.Get(path) 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)) }
查询参数的值使用 url.QueryEscape
进行转义。
$ go run get_req_params.go { "args": { "name": "John Doe", "occupation": "gardener" }, "headers": { "Accept-Encoding": "gzip", "Host": "httpbin.org", "User-Agent": "Go-http-client/2.0", "X-Amzn-Trace-Id": "Root=1-6000718d-443f64a345d2252d39b49b8d" }, ... "url": "https://httpbin.org/get?name=John+Doe&occupation=gardener" }
Go HTTP POST 请求 FORM 数据
PostForm
向指定 URL 发出 POST 请求,将数据的键和值 URL 编码为请求正文。Content-Type 头被设置为 application/x-www-form-urlencoded。数据以键值对的形式发送,键值对之间用 '&' 分隔,键和值之间用 '=' 分隔。
package main import ( "encoding/json" "fmt" "log" "net/http" "net/url" ) func main() { data := url.Values{ "name": {"John Doe"}, "occupation": {"gardener"}, } resp, err := http.PostForm("https://httpbin.org/post", data) if err != nil { log.Fatal(err) } defer resp.Body.Close() var res map[string]interface{} json.NewDecoder(resp.Body).Decode(&res) fmt.Println(res["form"]) }
我们向 https://httpbin.org/post
页面发送一个 POST 请求。
resp, err := http.PostForm("https://httpbin.org/post", data)
数据使用 PostForm
函数发送。
var res map[string]interface{} json.NewDecoder(resp.Body).Decode(&res)
我们将响应体解码到一个 map 中。
fmt.Println(res["form"])
我们打印接收到的数据。
$ go run post_req_form.go map[name:John Doe occupation:gardener]
Go HTTP POST 请求 JSON 数据
以下示例发送一个以 JSON 格式发送数据的 POST 请求。
package main import ( "bytes" "encoding/json" "fmt" "log" "net/http" ) func main() { values := map[string]string{"name": "John Doe", "occupation": "gardener"} json_data, err := json.Marshal(values) if err != nil { log.Fatal(err) } resp, err := http.Post("https://httpbin.org/post", "application/json", bytes.NewBuffer(json_data)) if err != nil { log.Fatal(err) } defer resp.Body.Close() var res map[string]interface{} json.NewDecoder(resp.Body).Decode(&res) fmt.Println(res["json"]) }
我们向 httpbin.org/post
网页生成一个 POST 请求。POST 数据来自一个 map,并使用 encoding/json
包转换为字符串。
values := map[string]string{"name": "John Doe", "occupation": "gardener"} json_data, err := json.Marshal(values)
使用 json.Marshal
将 map 序列化为 JSON 字符串。
resp, err := http.Post("https://httpbin.org/post", "application/json", bytes.NewBuffer(json_data))
当发送数据时,我们将 content type 设置为 application/json
。
$ go run post_req_json.go map[name:John Doe occupation:gardener]
来源
在本文中,我们创建了 Go 中的 GET 和 POST 请求。