GoClub Pro

Go-net/http

最近更新:2026-10-24
本页是手写/批注类笔记,直接按原始笔记截图呈现(转成文字会乱序);原始笔记文件见「Go语言相关笔记」页的原始链接。
onenote-go-net-http 原始笔记截图 1

附件文档全文(net http )#

net/http包详解

你想要全面了解 Go 语言中 net/http 包的核心功能、使用方式,并掌握其中的关键方法,这是学习 Go 后端开发的核心知识点之一。

net/http 是 Go 标准库中用于处理 HTTP 协议的核心包,它既可以快速搭建 HTTP 服务器,也能作为客户端发送 HTTP 请求,设计简洁且高性能,是 Go 做 Web 开发的基础。下面我会从服务器端、客户端、核心类型与方法三个维度,全面讲解这个包。

一、核心概念与整体架构

net/http 包的核心设计围绕两个核心角色:

  1. Server(服务器):监听端口、接收请求、路由分发、处理响应。
  2. Client(客户端):构造请求、发送请求、接收响应。

核心类型包括:ServeMux(路由多路复用器)、Handler(请求处理器)、Request(请求对象)、Response(响应对象)等。

二、服务器端:搭建 HTTP 服务

1. 最简 HTTP 服务器(快速入门)

通过 http.HandleFunc 注册路由处理函数,http.ListenAndServe 启动服务:

Go
package main

import (
"fmt"
"net/http"
)

// 处理根路径请求的函数(符合 http.HandlerFunc 签名)
func helloHandler(w http.ResponseWriter, r *http.Request) {
// w:响应写入器,用于向客户端返回数据;r:请求对象,包含客户端请求的所有信息
fmt.Fprintf(w, "Hello, Go HTTP! Path: %s", r.URL.Path)
}

func main() {
// 1. 注册路由:将路径 "/" 与处理函数绑定
http.HandleFunc("/", helloHandler)

// 2. 启动 HTTP 服务,监听 8080 端口
// 第一个参数:监听地址(":8080" 表示所有网卡的 8080 端口)
// 第二个参数:路由多路复用器(nil 表示使用默认的 DefaultServeMux)
fmt.Println("Server starting on :8080...")
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Printf("Server failed: %v\n", err)
}
}

运行后访问 http://localhost:8080,即可看到响应内容。

2. 服务器端核心类型与方法

(1)http.Handler 接口(核心处理器)

所有能处理 HTTP 请求的类型都必须实现这个接口,定义如下:

Go
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

自定义处理器示例(实现 Handler 接口):

Go
type MyHandler struct{}

// 实现 ServeHTTP 方法
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Custom Handler!"))
}

func main() {
handler := &MyHandler{}
http.Handle("/custom", handler) // 注册自定义处理器
http.ListenAndServe(":8080", nil)
}

(2)http.HandlerFunc(函数适配器)

本质是一个类型,实现了 Handler 接口,允许将普通函数(签名为 func(ResponseWriter, *Request))作为处理器:

Go
type HandlerFunc func(ResponseWriter, *Request)

// 实现 ServeHTTP 方法,调用自身
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}

这也是 http.HandleFunc 能直接接收普通函数的原因。

(3)http.ServeMux(路由多路复用器)

负责将不同的 URL 路径映射到对应的处理器,默认的 DefaultServeMux 是一个全局的 ServeMux 实例。

核心方法:

方法

作用

NewServeMux() *ServeMux

创建一个新的路由多路复用器(推荐自定义,避免全局冲突)

mux.Handle(pattern string, handler Handler)

注册路径与处理器的映射

mux.HandleFunc(pattern string, fn func(ResponseWriter, *Request))

简化版,直接注册函数处理器

mux.ServeHTTP(w ResponseWriter, r *Request)

实现 Handler 接口,分发请求到对应处理器

自定义 ServeMux 示例:

Go
func main() {
// 创建自定义路由
mux := http.NewServeMux()
mux.HandleFunc("/", helloHandler)
mux.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("User Page"))
})

// 启动服务时指定自定义 mux
http.ListenAndServe(":8080", mux)
}

(4)http.Server(自定义服务器配置)

ListenAndServe 是封装后的简化方法,若需自定义超时、TLS、地址等,可直接使用 http.Server:

核心字段与方法:

Go
// 核心字段
type Server struct {
Addr string // 监听地址(如 ":8080")
Handler Handler // 路由处理器(默认 DefaultServeMux)
ReadTimeout time.Duration // 读取请求的超时时间
WriteTimeout time.Duration // 写入响应的超时时间
MaxHeaderBytes int // 请求头最大字节数
// 其他字段:TLSConfig、IdleTimeout 等
}

// 核心方法
func (s *Server) ListenAndServe() error // 启动 HTTP 服务
func (s *Server) ListenAndServeTLS(certFile, keyFile string) error // 启动 HTTPS 服务
func (s *Server) Shutdown(ctx context.Context) error // 优雅关闭服务(不中断现有请求)

自定义 Server 示例:

Go
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", helloHandler)

// 配置自定义服务器
server := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: 10 * time.Second, // 读取超时 10 秒
WriteTimeout: 10 * time.Second, // 写入超时 10 秒
MaxHeaderBytes: 1 << 20, // 最大请求头 1MB
}

fmt.Println("Custom server starting on :8080...")
err := server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
fmt.Printf("Server failed: %v\n", err)
}
}

(5)http.ResponseWriter(响应写入器)

用于向客户端发送响应,核心方法:

方法

作用

Write([]byte) (int, error)

向响应体写入字节数据(自动设置 Content-Type 为 text/plain)

WriteHeader(int)

设置 HTTP 响应状态码(如 404、500),必须在 Write 之前调用

Header() Header

获取响应头映射,用于设置自定义响应头(如 Content-Type、Cookie)

示例:

Go
func handler(w http.ResponseWriter, r *http.Request) {
// 设置响应头
w.Header().Set("Content-Type", "application/json; charset=utf-8")
// 设置状态码
w.WriteHeader(http.StatusCreated) // 201
// 写入响应体
w.Write([]byte(`{"code":200,"msg":"success"}`))
}

(6)http.Request(请求对象)

封装了客户端的 HTTP 请求信息,核心字段/方法:

字段/方法

作用

r.Method

请求方法(GET/POST/PUT/DELETE 等)

r.URL

请求 URL(包含 Path、Query 参数等)

r.Header

请求头映射

r.Body

请求体(io.ReadCloser 类型,需手动关闭)

r.FormValue(key string)

获取 Form/Query 参数(自动解析,优先 PostForm)

r.PostFormValue(key string)

仅获取 POST 表单参数

r.Cookies()

获取所有 Cookie

r.RemoteAddr

客户端地址

r.ParseForm() error

手动解析 Form 数据(FormValue 会自动调用)

示例:

Go
func formHandler(w http.ResponseWriter, r *http.Request) {
// 解析表单(POST 需手动调用,GET 自动)
err := r.ParseForm()
if err != nil {
http.Error(w, "解析表单失败", http.StatusBadRequest)
return
}

// 获取 Query 参数
name := r.FormValue("name")
// 获取 POST 表单参数
age := r.PostFormValue("age")

fmt.Fprintf(w, "Name: %s, Age: %s", name, age)
}

三、客户端:发送 HTTP 请求

net/http 也提供了完整的 HTTP 客户端能力,核心是 http.Client 类型。

1. 最简请求(封装方法)

http 包提供了直接发送 GET/POST 等请求的快捷方法:

(1)http.Get(url string) (*Response, error)

发送 GET 请求:

Go
func main() {
// 发送 GET 请求
resp, err := http.Get("https://httpbin.org/get")
if err != nil {
fmt.Printf("Get failed: %v\n", err)
return
}
defer resp.Body.Close() // 必须关闭响应体,避免内存泄漏

// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Read body failed: %v\n", err)
return
}

fmt.Printf("Status: %s\nBody: %s\n", resp.Status, string(body))
}

(2)http.Post(url, contentType string, body io.Reader) (*Response, error)

发送 POST 请求:

Go
func main() {
// 构造 POST 表单数据
data := url.Values{}
data.Set("name", "go")
data.Set("age", "10")

// 发送 POST 请求(contentType 为 application/x-www-form-urlencoded)
resp, err := http.Post("https://httpbin.org/post",
"application/x-www-form-urlencoded",
strings.NewReader(data.Encode()))
if err != nil {
fmt.Printf("Post failed: %v\n", err)
return
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}

(3)http.PostForm(url string, data url.Values) (*Response, error)

简化版 POST 表单请求(自动设置 contentType):

Go
resp, err := http.PostForm("https://httpbin.org/post", url.Values{"name": {"go"}, "age": {"10"}})

(4)http.Head(url string) (*Response, error)

发送 HEAD 请求(仅返回响应头,无响应体):

Go
resp, err := http.Head("https://httpbin.org/get")
fmt.Println(resp.Status) // 打印状态码
fmt.Println(resp.Header) // 打印响应头

2. 自定义客户端(http.Client)

快捷方法使用的是全局默认客户端 http.DefaultClient,自定义客户端可配置超时、代理、Cookie 等:

Go
func main() {
// 自定义客户端配置
client := &http.Client{
Timeout: 10 * time.Second, // 请求超时 10 秒
// Transport: &http.Transport{ // 自定义传输层(代理、TLS 等)
// Proxy: http.ProxyFromEnvironment,
// TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 跳过 HTTPS 证书验证(测试用)
// },
}

// 构造自定义请求(支持设置请求头、Method 等)
req, err := http.NewRequest("PUT", "https://httpbin.org/put", strings.NewReader(`{"key":"value"}`))
if err != nil {
fmt.Printf("Create request failed: %v\n", err)
return
}

// 设置请求头
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "Go-Client/1.0")

// 发送请求
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Do request failed: %v\n", err)
return
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}

http.Client 核心方法:

方法

作用

client.Do(req *Request) (*Response, error)

发送自定义请求(最核心,支持所有 HTTP 方法)

client.Get(url string) (*Response, error)

封装的 GET 请求(内部调用 Do)

client.Post(url, contentType string, body io.Reader) (*Response, error)

封装的 POST 请求

client.PostForm(url string, data url.Values) (*Response, error)

封装的表单 POST 请求

3. http.Response(客户端响应对象)

客户端接收到的响应,核心字段/方法:

字段/方法

作用

resp.Status

响应状态(如 "200 OK")

resp.StatusCode

响应状态码(如 200、404)

resp.Header

响应头映射

resp.Body

响应体(io.ReadCloser 类型,必须关闭)

resp.Cookies()

获取响应中的 Cookie

四、其他常用工具方法

方法

作用

http.Error(w ResponseWriter, error string, code int)

快速返回错误响应(自动设置状态码和响应体)

http.Redirect(w ResponseWriter, r *Request, url string, code int)

重定向(常用 301/302)

http.SetCookie(w ResponseWriter, cookie *Cookie)

向响应中添加 Cookie

http.DetectContentType(data []byte) string

检测数据的 Content-Type(如 text/html、application/json)

示例:

Go
// 快速返回 404 错误
func notFoundHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Page Not Found", http.StatusNotFound)
}

// 重定向
func redirectHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://www.google.com", http.StatusTemporaryRedirect)
}

// 设置 Cookie
func cookieHandler(w http.ResponseWriter, r *http.Request) {
cookie := &http.Cookie{
Name: "token",
Value: "123456",
Path: "/",
MaxAge: 3600, // 有效期 1 小时
}
http.SetCookie(w, cookie)
w.Write([]byte("Cookie set!"))
}

总结

  1. net/http 包核心分为服务器端和客户端两大能力:服务器端通过 Handler/ServeMux/Server 搭建服务,客户端通过 Client/Request/Response 发送请求。
  2. 服务器端核心是 Handler 接口,所有处理器都需实现它;HandlerFunc 是函数适配器,简化普通函数作为处理器的流程。
  3. 客户端开发中,简单场景用 http.Get/Post 等快捷方法,复杂场景(超时、代理、自定义头)用 http.Client + http.NewRequest 实现,且必须关闭 resp.Body 避免资源泄漏。

掌握这些核心类型和方法,就能覆盖大部分 HTTP 开发场景,进阶可结合中间件(如日志、鉴权)、路由框架(如 gin)扩展能力。

|(注:文档部分内容可能由 AI 生成)

附件原文:onenote-go-net-http-net_http_.docx(点击下载)

转换文字版(供搜索 / 复制)
内容反馈

发现错误或想补充内容?

GoClub Pro 是静态知识库,评论功能不再加载第三方脚本。你可以在 GitHub 仓库提交 Issue,反馈会直接进入项目协作流程。

提交 GitHub 反馈