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

以下是 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 创建基本服务器

go 复制代码
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
go 复制代码
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 (使用自定义处理器)
go 复制代码
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 进行多路复用

go 复制代码
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 中间件模式

go 复制代码
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 文件服务器

go 复制代码
func main() {
	// 静态文件服务
	fs := http.FileServer(http.Dir("static/"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))
	
	http.ListenAndServe(":8080", nil)
}

四、 HTTP 客户端功能

4.1 发送 GET 请求

go 复制代码
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 请求

go 复制代码
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)

go 复制代码
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 响应

go 复制代码
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 设置超时

go 复制代码
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()
	
	// 处理响应...
}
go 复制代码
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!")
}
go 复制代码
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 服务器

go 复制代码
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 处理文件上传

go 复制代码
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 响应,主要方法:

go 复制代码
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

包含客户端请求的所有信息:

go 复制代码
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

go 复制代码
func main() {
	// 将 /static/ 前缀去掉后再查找文件
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("assets"))))
	http.ListenAndServe(":8080", nil)
}

7.2 http.Redirect

go 复制代码
func redirectHandler(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "https://example.com/new-location", http.StatusMovedPermanently)
}

7.3 http.NotFound

go 复制代码
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 已经能够满足大多数基本需求。

相关推荐
咖啡八杯7 分钟前
GoF设计模式——模板方法模式
java·后端·spring·设计模式
码事漫谈1 小时前
Loop 正在排斥人为操作
后端
爱勇宝1 小时前
办公资料反复修改、补传、交接混乱,我做了个桌面工具来解决这件事
前端·后端·程序员
2zcode1 小时前
基于MATLAB图像处理的饮料瓶灌装液位检测系统设计与实现
开发语言·图像处理·matlab
庄周de蝴蝶2 小时前
梅开二度,这次拿下系统分析师
后端·程序员
必须得开心呀2 小时前
QT解决中文乱码问题
开发语言·qt
林小帅3 小时前
NestJS v11 + Prisma v7 ESM 迁移配置解析
前端·javascript·后端
IT_陈寒3 小时前
React的setState竟然不是立刻生效的,害我调试半天
前端·人工智能·后端
这不小天嘛3 小时前
JAVA八股——redis篇
java·开发语言·redis
阿里云云原生4 小时前
不改代码也能监控 AI Agent?揭秘 OBI 如何在内核层精准解析 GenAI 语义流量
云原生·agent