作为 HTTP 客户端 使用 Go 的 net/http
模块时,重点在于如何发送各种 HTTP 请求、处理响应以及灵活使用客户端配置。下面分为常见场景和进阶功能讲解。
1. 基础 HTTP 客户端操作
GET 请求
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
// 简单 GET 请求
resp, err := http.Get("https://jsonplaceholder.typicode.com/posts/1")
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 读取响应体
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println("Status Code:", resp.StatusCode) // 打印状态码
fmt.Println("Body:", string(body)) // 打印响应体
}
POST 请求
发送 JSON 数据:
package main
import (
"bytes"
"fmt"
"net/http"
)
func main() {
data := []byte(`{"title":"foo","body":"bar","userId":1}`)
resp, err := http.Post("https://jsonplaceholder.typicode.com/posts", "application/json", bytes.NewBuffer(data))
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Status Code:", resp.StatusCode)
}
2. 使用 http.Client
发送自定义请求
http.Client
提供更多控制,适合复杂场景。
自定义请求
通过 http.NewRequest
创建请求,可以添加自定义头部、方法等:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func main() {
client := &http.Client{}
// 创建请求
req, err := http.NewRequest("POST", "https://jsonplaceholder.typicode.com/posts", strings.NewReader(`{"name":"test"}`))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer your_token")
// 发送请求
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 读取响应
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println("Response:", string(body))
}
3. 进阶功能
设置超时
避免请求无限制地挂起,使用 http.Client
设置超时:
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
client := &http.Client{
Timeout: 5 * time.Second,
}
resp, err := client.Get("https://jsonplaceholder.typicode.com/posts/1")
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Status Code:", resp.StatusCode)
}
处理 Cookie
通过 http.Cookie
发送或接收 Cookie:
package main
import (
"fmt"
"net/http"
)
func main() {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://example.com", nil)
// 设置 Cookie
req.AddCookie(&http.Cookie{Name: "session_id", Value: "123456"})
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 打印响应 Cookie
for _, cookie := range resp.Cookies() {
fmt.Println("Cookie:", cookie)
}
}
处理重定向
http.Client
默认跟随重定向,但可以自定义行为:
package main
import (
"fmt"
"net/http"
)
func main() {
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
fmt.Println("Redirected to:", req.URL)
return nil // 返回错误可阻止重定向
},
}
resp, err := client.Get("http://example.com")
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Final URL:", resp.Request.URL)
}
4. 文件上传和下载
文件上传
使用 multipart.Writer
构造文件上传请求:
package main
import (
"bytes"
"fmt"
"mime/multipart"
"net/http"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
panic(err)
}
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", "example.txt")
if err != nil {
panic(err)
}
_, err = part.Write([]byte("file content"))
if err != nil {
panic(err)
}
writer.Close()
req, _ := http.NewRequest("POST", "https://example.com/upload", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Status Code:", resp.StatusCode)
}
文件下载
将响应流直接保存到文件中:
package main
import (
"io"
"net/http"
"os"
)
func main() {
resp, err := http.Get("https://example.com/file.zip")
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, err := os.Create("file.zip")
if err != nil {
panic(err)
}
defer out.Close()
_, err = io.Copy(out, resp.Body) // 保存到本地文件
if err != nil {
panic(err)
}
}
5. 常见问题
并发请求
使用goroutines
实现并发请求:go func(url string) { resp, _ := http.Get(url) defer resp.Body.Close() // 处理响应 }("https://example.com")
Debug 请求和响应
利用net/http/httputil
打印完整信息:req, _ := http.NewRequest("GET", "https://example.com", nil) dump, _ := httputil.DumpRequestOut(req, true) fmt.Println(string(dump))
如果你有具体的功能需求,可以进一步展开讲解!