以下是 Go 语言 net/http 模块的完整方法详解及示例,涵盖所有核心功能:
一、常量
常见的HTTP方法
变量名 | 值 | 备注 |
---|---|---|
MethodGet | GET | |
MethodHead | HEAD | |
MethodPost | POST | |
MethodPut | PUT | |
MethodPatch | PATCH | |
MethodDelete | PATCH | RFC 5789 |
MethodDelete | DELETE | |
MethodConnect | CONNECT | |
MethodOptions | OPTIONS | |
MethodTrace | TRACE |
IANA注册的HTTP状态代码
变量名 | 值 | 备注 |
---|---|---|
StatusContinue | 100 | // RFC 9110, 15.2.1 |
StatusSwitchingProtocols | 101 | // RFC 9110, 15.2.2 |
StatusProcessing | 102 | // RFC 2518, 10.1 \ |
StatusEarlyHints | 103 | // RFC 8297 \ |
StatusOK | 200 | // RFC 9110, 15.3.1 \ |
StatusCreated | 201 | // RFC 9110, 15.3.2 \ |
StatusAccepted | 202 | // RFC 9110, 15.3.3 \ |
StatusNonAuthoritativeInfo | 203 | // RFC 9110, 15.3.4 \ |
StatusNoContent | 204 | // RFC 9110, 15.3.5 \ |
StatusResetContent | 205 | // RFC 9110, 15.3.6 \ |
StatusPartialContent | 206 | // RFC 9110, 15.3.7 \ |
StatusMultiStatus | 207 | // RFC 4918, 11.1 \ |
StatusAlreadyReported | 208 | // RFC 5842, 7.1 \ |
StatusIMUsed | 226 | // RFC 3229, 10.4.1 \ |
StatusMultipleChoices | 300 | // RFC 9110, 15.4.1 \ |
StatusMovedPermanently | 301 | // RFC 9110, 15.4.2 \ |
StatusFound | 302 | // RFC 9110, 15.4.3 \ |
StatusSeeOther | 303 | // RFC 9110, 15.4.4 \ |
StatusNotModified | 304 | // RFC 9110, 15.4.5 \ |
StatusUseProxy | 305 | // RFC 9110, 15.4.6 \ |
StatusTemporaryRedirect | 307 | // RFC 9110, 15.4.8 \ |
StatusPermanentRedirect | 308 | // RFC 9110, 15.4.9 \ |
StatusBadRequest | 400 | // RFC 9110, 15.5.1 \ |
StatusUnauthorized | 401 | // RFC 9110, 15.5.2 \ |
StatusPaymentRequired | 402 | // RFC 9110, 15.5.3 \ |
StatusForbidden | 403 | // RFC 9110, 15.5.4 \ |
StatusNotFound | 404 | // RFC 9110, 15.5.5 \ |
StatusMethodNotAllowed | 405 | // RFC 9110, 15.5.6 \ |
StatusNotAcceptable | 406 | // RFC 9110, 15.5.7 \ |
StatusProxyAuthRequired | 407 | // RFC 9110, 15.5.8 \ |
StatusRequestTimeout | 408 | // RFC 9110, 15.5.9 \ |
StatusConflict | 409 | // RFC 9110, 15.5.10 \ |
StatusGone | 410 | // RFC 9110, 15.5.11 \ |
StatusLengthRequired | 411 | // RFC 9110, 15.5.12 \ |
StatusPreconditionFailed | 412 | // RFC 9110, 15.5.13 \ |
StatusRequestEntityTooLarge | 413 | // RFC 9110, 15.5.14 \ |
StatusRequestURITooLong | 414 | // RFC 9110, 15.5.15 \ |
StatusUnsupportedMediaType | 415 | // RFC 9110, 15.5.16 \ |
StatusRequestedRangeNotSatisfiable | 416 | // RFC 9110, 15.5.17 \ |
StatusExpectationFailed | 417 | // RFC 9110, 15.5.18 \ |
StatusTeapot | 418 | // RFC 9110, 15.5.19 (Unused) \ |
StatusMisdirectedRequest | 421 | // RFC 9110, 15.5.20 \ |
StatusUnprocessableEntity | 422 | // RFC 9110, 15.5.21 \ |
StatusLocked | 423 | // RFC 4918, 11.3 \ |
StatusFailedDependency | 424 | // RFC 4918, 11.4 \ |
StatusTooEarly | 425 | // RFC 8470, 5.2. \ |
StatusUpgradeRequired | 426 | // RFC 9110, 15.5.22 \ |
StatusPreconditionRequired | 428 | // RFC 6585, 3 \ |
StatusTooManyRequests | 429 | // RFC 6585, 4 \ |
StatusRequestHeaderFieldsTooLarge | 431 | // RFC 6585, 5 \ |
StatusUnavailableForLegalReasons | 451 | // RFC 7725, 3 \ |
StatusInternalServerError | 500 | // RFC 9110, 15.6.1 \ |
StatusNotImplemented | 501 | // RFC 9110, 15.6.2 \ |
StatusBadGateway | 502 | // RFC 9110, 15.6.3 \ |
StatusServiceUnavailable | 503 | // RFC 9110, 15.6.4 \ |
StatusGatewayTimeout | 504 | // RFC 9110, 15.6.5 \ |
StatusHTTPVersionNotSupported | 505 | // RFC 9110, 15.6.6 \ |
StatusVariantAlsoNegotiates | 506 | // RFC 2295, 8.1 \ |
StatusInsufficientStorage | 507 | // RFC 4918, 11.5 \ |
StatusLoopDetected | 508 | // RFC 5842, 7.2 \ |
StatusNotExtended | 510 | // RFC 2774, 7 \ |
StatusNetworkAuthenticationRequired | 511 | // RFC 6585, 6 \ |
变量名 | 值 | 备注 |
---|---|---|
DefaultMaxHeaderBytes | 1 << 20 | // 1 MB DefaultMaxHeaderBytes 是标头的最大允许大小 在 HTTP 请求中。 这可以通过设置 [Server.MaxHeaderBytes] 来覆盖。 |
DefaultMaxIdleConnsPerHost | 2 | DefaultMaxIdleConnsPerHost 是 Transport 的 MaxIdleConnsPerHost 的 |
TimeFormat | “Mon, 02 Jan 2006 15:04:05 GMT” | TimeFormat 是在 HTTP 中生成时间时使用的时间格式 头。这就像时间。RFC1123但将 GMT 硬编码为时间 区。要格式化的时间必须采用 UTC 格式,以便将 Format (格式) 设置为 生成正确的格式。 |
TrailerPrefix | “Trailer:” | TrailerPrefix 是 [ResponseWriter.Header] 映射键的魔术前缀 如果存在,则表示 Map 条目实际上是用于 响应尾部,而不是响应标头。前缀 在 ServeHTTP 调用完成后被剥离,值为 在拖车中发送。 |
此机制仅适用于未知的拖车 在写入标头之前。如果拖车组是固定的 或者在写入 header 之前就知道,正常的 Go trailers 机制 是首选:https://pkg.go.dev/net/http#ResponseWriter https://pkg.go.dev/net/http#example-ResponseWriter-Trailers |
二、变量
变量名 | 值 | 备注 |
---|---|---|
ErrNotSupported | &ProtocolError{“feature not supported”} | 特性不支持 |
ErrUnexpectedTrailer | &ProtocolError{“trailer header without chunked transfer encoding”} | 已弃用: net/http 包中的任何内容都不再返回 ErrUnexpectedTrailer。调用方不应将错误与此变量进行比较。 |
ErrMissingBoundary | &ProtocolError{“no multipart boundary param in Content-Type”} | 当请求的 Content-Type 不包含“boundary”参数时,Request.MultipartReader 会返回 ErrMissingBoundary。 |
ErrNotMultipart | &ProtocolError{“request Content-Type isn’t multipart/form-data”} | 当请求的 Content-Type 不是 multipart/form-data 时,Request.MultipartReader 会返回 ErrNotMultipart。 |
ErrHeaderTooLong | &ProtocolError{“header too long”} | 已弃用: net/http 包中的任何内容都不再返回 ErrHeaderTooLong。调用方不应将错误与此变量进行比较。 |
ErrShortBody | &ProtocolError{“entity body too short”} | 已弃用: net/http 包中的任何内容都不再返回 ErrShortBody。调用方不应将错误与此变量进行比较。 |
ErrMissingContentLength | &ProtocolError{“missing ContentLength in HEAD response”} | 已弃用: net/http 包中的任何内容都不再返回 ErrMissingContentLength。调用方不应将错误与此变量进行比较。 |
ErrBodyNotAllowed | errors.New(“http: request method or response status code does not allow body”) | 当 HTTP 方法或响应代码不允许正文时,ResponseWriter.Write 调用会返回 ErrBodyNotAllowed。 |
ErrHijacked | errors.New(“http: connection has been hijacked”) | 当底层连接使用 Hijacker 接口被劫持时,ErrHijacked 由 ResponseWriter.Write 调用返回。对被劫持的连接进行零字节写入将返回 ErrHijacked,而不会产生任何其他副作用。 |
ErrContentLength | errors.New(“http: wrote more than the declared Content-Length”) | 当 Handler 使用声明的大小设置 Content-Length 响应标头,然后尝试写入比声明的字节数更多的字节时,ResponseWriter.Write 调用会返回 ErrContentLength。 |
ErrWriteAfterFlush | errors.New(“unused”) | 已弃用:net/http 包中的任何内容都不再返回 ErrWriteAfterFlush。调用方不应将错误与此变量进行比较。 |
HTTP 服务器使用的错误。
变量名 | 值 | 备注 |
---|---|---|
ServerContextKey | &contextKey{“http-server”} | ServerContextKey 是上下文键。它可以在 HTTP 处理程序中使用 Context.Value 来访问启动处理程序的服务器。关联的值将为 *Server 类型。 |
LocalAddrContextKey | &contextKey{“local-addr”} | LocalAddrContextKey 是上下文键。它可以在具有 Context.Value 的 HTTP 处理程序中使用,以访问连接到达的本地地址。关联的值将为 net 类型。地址。 |
DefaultClient | &Client{} | DefaultClient 是默认 Client,由 Get、Head 和 Post 使用。 |
DefaultServeMux | &defaultServeMux | DefaultServeMux 是 Serve 使用的默认 ServeMux。 |
ErrAbortHandler | errors.New(“net/http: abort Handler”) | ErrAbortHandler 是用于中止处理程序的 sentinel panic 值。 虽然来自 ServeHTTP 的任何 panic 都会中止对客户端的响应, 使用 ErrAbortHandler 进行 panic 也会抑制堆栈的日志记录 trace 到服务器的错误日志。 |
ErrBodyReadAfterClose | errors.New(“http: invalid Read on closed Body”) | ErrBodyReadAfterClose 在正文关闭后读取请求或响应正文时返回。这通常发生在身体 在 HTTP 处理程序对其 ResponseWriter 调用 WriteHeader 或 Write 之后读取。 |
ErrHandlerTimeout | errors.New(“http: Handler timeout”) | ErrHandlerTimeout 在 ResponseWriter Write 调用时返回 在已超时的处理程序中。 |
ErrLineTooLong | internal.ErrLineTooLong | 读取请求或响应正文时返回 ErrLineTooLong 使用格式错误的分块编码。 |
ErrMissingFile | errors.New(“http: no such file”) | 当提供的文件字段名称时,FormFile 会返回 ErrMissingFile 要么不存在于请求中,要么不是 file 字段。 |
ErrNoCookie | errors.New(“http: named cookie not present”) | 当找不到 Cookie 时,Request 的 Cookie 方法会返回 ErrNoCookie。 |
ErrNoLocation | errors.New(“http: no Location header in response”) | ErrNoLocation 由 Response.Location 方法返回 当不存在 Location 标头时。 |
ErrSchemeMismatch | errors.New(“http: server gave HTTP response to HTTPS client”) | 当服务器向 HTTPS 客户端返回 HTTP 响应时,将返回 ErrSchemeMismatch。 |
ErrServerClosed | errors.New(“http: Server closed”) | ErrServerClosed 由 Server.Serve、ServeTLS、ListenAndServe、 和 ListenAndServeTLS 方法。 |
ErrSkipAltProtocol | errors.New(“net/http: skip alternate protocol”) | ErrSkipAltProtocol 是由 Transport.RegisterProtocol 定义的 sentinel 错误值。 |
ErrUseLastResponse | errors.New(“net/http: use last response”) | ErrUseLastResponse 可以通过 Client.CheckRedirect 钩子返回给 控制重定向的处理方式。如果返回,则为下一个请求 未发送,并且最近的响应将返回其正文 未关闭。 |
NoBody | noBody{} | NoBody 是 io。ReadCloser 的 URL 中。读取始终返回 EOF 和 Close 始终返回 nil。它可以在传出客户端中使用 请求显式表示请求具有零字节。 但是,另一种方法是简单地将 [Request.Body] 设置为 nil。 |
三.、HTTP 服务器功能方法
3.1 创建基本服务器
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/hello", helloHandler)
fmt.Println("Server starting on port 8080...")
http.ListenAndServe(":8080", nil)
}
3.2 路由处理
http.HandleFunc
http.HandleFunc("/greet", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if name == "" {
name = "Guest"
}
fmt.Fprintf(w, "Hello, %s!", name)
})
http.Handle (使用自定义处理器)
type greetingHandler struct{}
func (h *greetingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the greeting page!")
}
func main() {
http.Handle("/greeting", &greetingHandler{})
http.ListenAndServe(":8080", nil)
}
3.3 使用 ServeMux 进行多路复用
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Home Page")
})
mux.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "About Page")
})
http.ListenAndServe(":8080", mux)
}
3.4 中间件模式
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%s %s\n", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
})
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Home Page")
})
http.ListenAndServe(":8080", loggingMiddleware(mux))
}
3.5 文件服务器
func main() {
// 静态文件服务
fs := http.FileServer(http.Dir("static/"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
http.ListenAndServe(":8080", nil)
}
四、 HTTP 客户端功能
4.1 发送 GET 请求
func main() {
resp, err := http.Get("https://api.example.com/data")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response:", err)
return
}
fmt.Println(string(body))
}
4.2 发送 POST 请求
func main() {
payload := strings.NewReader(`{"name":"John","age":30}`)
resp, err := http.Post(
"https://api.example.com/users",
"application/json",
payload,
)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
// 处理响应...
}
4.3 自定义请求 (使用 http.NewRequest)
func main() {
payload := strings.NewReader(`{"query":"search term"}`)
req, err := http.NewRequest(
"POST",
"https://api.example.com/search",
payload,
)
if err != nil {
fmt.Println("Error creating request:", err)
return
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer abc123")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
// 处理响应...
}
4.4 处理 JSON 响应
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func main() {
resp, err := http.Get("https://api.example.com/users/1")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
var user User
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
fmt.Println("Error decoding JSON:", err)
return
}
fmt.Printf("User: %+v\n", user)
}
五、 高级功能
5.1 设置超时
func main() {
client := &http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Get("https://api.example.com/slow-endpoint")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
// 处理响应...
}
5.2 处理 Cookie
服务器设置 Cookie
func setCookieHandler(w http.ResponseWriter, r *http.Request) {
cookie := &http.Cookie{
Name: "session_id",
Value: "abc123",
Path: "/",
MaxAge: 3600,
}
http.SetCookie(w, cookie)
fmt.Fprintf(w, "Cookie set!")
}
客户端发送 Cookie
func main() {
req, err := http.NewRequest("GET", "https://api.example.com/protected", nil)
if err != nil {
fmt.Println("Error:", err)
return
}
cookie := &http.Cookie{
Name: "session_id",
Value: "abc123",
}
req.AddCookie(cookie)
client := &http.Client{}
resp, err := client.Do(req)
// 处理响应...
}
5.3 HTTPS 服务器
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Secure Hello World!")
})
err := http.ListenAndServeTLS(
":443",
"server.crt",
"server.key",
nil,
)
if err != nil {
fmt.Println("Error starting server:", err)
}
}
5.4 处理文件上传
func uploadHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 解析 multipart 表单,限制上传大小为 10MB
err := r.ParseMultipartForm(10 << 20)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
file, handler, err := r.FormFile("myFile")
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer file.Close()
// 创建目标文件
dst, err := os.Create(handler.Filename)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer dst.Close()
// 复制文件内容
if _, err := io.Copy(dst, file); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "File uploaded successfully: %s", handler.Filename)
}
func main() {
http.HandleFunc("/upload", uploadHandler)
http.ListenAndServe(":8080", nil)
}
六、 重要类型和接口
6.1 http.ResponseWriter
用于构造 HTTP 响应,主要方法:
func handler(w http.ResponseWriter, r *http.Request) {
// 设置状态码
w.WriteHeader(http.StatusOK)
// 设置响应头
w.Header().Set("Content-Type", "application/json")
w.Header().Add("X-Custom-Header", "value")
// 写入响应体
fmt.Fprintf(w, `{"status":"ok"}`)
}
6.2 http.Request
包含客户端请求的所有信息:
func handler(w http.ResponseWriter, r *http.Request) {
// 请求方法
method := r.Method
// URL 信息
path := r.URL.Path
query := r.URL.Query().Get("param")
// 请求头
contentType := r.Header.Get("Content-Type")
// 请求体
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 表单数据
formValue := r.FormValue("key")
// 打印一些信息
fmt.Printf("Method: %s, Path: %s, Query: %s\n", method, path, query)
fmt.Printf("Content-Type: %s, Body: %s, FormValue: %s\n", contentType, body, formValue)
}
七、 实用工具函数
7.1 http.StripPrefix
func main() {
// 将 /static/ 前缀去掉后再查找文件
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("assets"))))
http.ListenAndServe(":8080", nil)
}
7.2 http.Redirect
func redirectHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://example.com/new-location", http.StatusMovedPermanently)
}
7.3 http.NotFound
func handler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/valid-path" {
http.NotFound(w, r)
return
}
fmt.Fprintf(w, "Valid path")
}
总结
net/http 包提供了构建 HTTP 客户端和服务器的完整工具集。通过上面的示例,我们可以看到:
- 创建 HTTP 服务器非常简单,只需几行代码
- 提供了灵活的路由处理机制
- 支持中间件模式,方便扩展功能
- 客户端 API 简洁但功能强大
- 内置支持 HTTPS、文件上传、Cookie 等常见功能
对于更高级的需求,可以结合第三方路由库(如 gorilla/mux)或框架(如 Gin、Echo)使用,但标准库的 net/http 已经能够满足大多数基本需求。