Go 语言 net/http模块的完整方法详解及示例

发布于:2025-03-28 ⋅ 阅读:(28) ⋅ 点赞:(0)

以下是 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 客户端和服务器的完整工具集。通过上面的示例,我们可以看到:

  1. 创建 HTTP 服务器非常简单,只需几行代码
  2. 提供了灵活的路由处理机制
  3. 支持中间件模式,方便扩展功能
  4. 客户端 API 简洁但功能强大
  5. 内置支持 HTTPS、文件上传、Cookie 等常见功能

对于更高级的需求,可以结合第三方路由库(如 gorilla/mux)或框架(如 Gin、Echo)使用,但标准库的 net/http 已经能够满足大多数基本需求。