Go 语言 net/http 包详解:从入门到实战

Go 语言的标准库 net/http 提供了强大的 HTTP 客户端和服务端实现,是构建 Web 应用和 API 的基础。本文将从零开始,带你全面掌握 net/http 包的使用,包括服务端搭建、请求处理、路由匹配、参数获取、最佳实践等内容,并重点介绍 Go 1.22 带来的路由增强特性。


一、HTTP 服务端基础

1.1 最简单的 HTTP 服务器

go

复制代码
package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", helloHandler)
    http.ListenAndServe(":8080", nil)
}

1.2 核心接口:http.Handler

任何实现了 ServeHTTP(ResponseWriter, *Request) 方法的类型都可以作为 HTTP 处理器。

go

复制代码
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

1.3 服务启动的两种方式

✅ 使用默认路由(包级别函数)

go

复制代码
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
✅ 自定义 Server 实例(推荐生产环境)

go

复制代码
s := &http.Server{
    Addr:           ":8080",
    Handler:        myHandler,
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServe())

1.4 支持 HTTPS

go

复制代码
http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)

二、请求与响应处理

2.1 核心对象

  • http.ResponseWriter:构造响应
  • *http.Request:获取请求信息

2.2 构建响应示例

go

复制代码
func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    w.Write([]byte(`{"status": "success"}`))
}

2.3 读取请求信息

go

复制代码
method := r.Method
path := r.URL.Path
userAgent := r.Header.Get("User-Agent")
ip := r.RemoteAddr

三、路由与路径匹配

3.1 基础路由注册

go

复制代码
http.HandleFunc("/", homeHandler)
http.HandleFunc("/users", usersHandler)

3.2 自定义 ServeMux

go

复制代码
mux := http.NewServeMux()
mux.HandleFunc("/", homeHandler)
http.ListenAndServe(":8080", mux)

3.3 Go 1.22+ 路由增强

✅ 方法匹配

go

复制代码
http.HandleFunc("GET /posts/{id}", handleGetPost)
http.HandleFunc("POST /posts", handleCreatePost)
✅ 路径通配符

go

复制代码
http.HandleFunc("GET /posts/{id}", func(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id")
    fmt.Fprintf(w, "Post ID: %s", id)
})
✅ 剩余路径匹配

go

复制代码
http.HandleFunc("GET /files/{path...}", func(w http.ResponseWriter, r *http.Request) {
    path := r.PathValue("path")
    fmt.Fprintf(w, "File path: %s", path)
})

3.4 路由优先级规则

  • 最具体模式获胜(Go 1.22+)
  • 传统规则:长路径优先

四、请求方法处理

4.1 方法判断

go

复制代码
switch r.Method {
case http.MethodGet:
    handleGet(w, r)
case http.MethodPost:
    handlePost(w, r)
}

4.2 Go 1.22+ 方法限定

go

复制代码
mux.HandleFunc("GET /users", listUsers)
mux.HandleFunc("POST /users", createUser)

4.3 第三方路由库(gorilla/mux)

go

复制代码
r := mux.NewRouter()
r.HandleFunc("/products/{id:[0-9]+}", productHandler)

五、请求参数处理

参数类型 获取方式 示例
查询参数 r.URL.Query().Get("key") /users?page=1
表单参数 r.FormValue("key") username=john
路径参数 r.PathValue("id") /users/123
JSON 请求体 json.NewDecoder(r.Body).Decode {"name":"john"}
原始请求体 io.ReadAll(r.Body) 二进制 / XML 等

JSON 解析示例

go

复制代码
var user User
err := json.NewDecoder(r.Body).Decode(&user)

六、完整示例:RESTful API(Go 1.22+)

go

复制代码
package main

import (
    "encoding/json"
    "net/http"
    "strconv"
    "sync"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
    Age  int    `json:"age"`
}

var (
    users   = make(map[int]User)
    nextID  = 1
    usersMu sync.RWMutex
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("GET /users", listUsers)
    mux.HandleFunc("POST /users", createUser)
    mux.HandleFunc("GET /users/{id}", getUser)
    mux.HandleFunc("PUT /users/{id}", updateUser)
    mux.HandleFunc("DELETE /users/{id}", deleteUser)
    http.ListenAndServe(":8080", mux)
}
// 各函数实现略(详见原文)

七、常见错误与最佳实践

❌ 常见错误

  • 未关闭响应体
  • 在写入响应体后调用 WriteHeader
  • 忽略错误处理
  • 未设置超时

✅ 最佳实践

  • 重用 HTTP 客户端
  • 使用 Context 控制超时
  • 统一响应格式
  • 输入验证
  • 优雅关闭服务器
优雅关闭示例

go

复制代码
srv := &http.Server{Addr: ":8080", Handler: mux}
go srv.ListenAndServe()

<-quit
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
srv.Shutdown(ctx)

八、总结

组件 关键类型/函数 用途
服务端 http.ListenAndServehttp.Server 启动服务
处理器 Handler 接口、HandleFunc 处理请求
请求 *http.Request 获取请求信息
响应 http.ResponseWriter 构建响应
路由 ServeMuxDefaultServeMux 路由分发
参数 URL.Query()FormValue()PathValue() 获取请求参数

Go 1.22+ 亮点

  • 方法匹配
  • 路径通配符
  • 最具体规则

学习建议

  1. 从标准库入手,理解 Handler 接口
  2. 注意 Go 版本差异(1.22 路由增强)
  3. 实践时注重错误处理、超时控制、资源关闭
相关推荐
GoFly开发者3 小时前
GoFly 社区 GMQT|国产自研 MQTT‑Broker,打造私有化物联网消息底座
物联网·mqtt·golang·mqtt broker·mqtt私有化部署
DsirNg4 小时前
一文讲清网络协议:从打开网页到理解 HTTP、HTTPS 与 TLS
http·https·dns·网络基础·入门教程·tls·web 安全
奈斯先生Vector4 小时前
2026 AIGC API 网关韧性评测:为什么 HTTP 200 不等于有效交付
网络协议·http·aigc
刘步权4 小时前
KY-RTI分布仿真技术:第十四章 Go程序设计
golang·hla·rti·高层体系结构·多语言仿真
谏书稀5 小时前
C++/Python 混合编程(CPython)中 GIL饥饿 导致的 HTTP 服务无响应问题与解决方案
c++·python·http
microrain13 小时前
从数据烟囱到融合中心:SagooIoT统一数据处理平台的设计实践
物联网·golang·开源·sagooiot
DLYSB_16 小时前
API 网关流量洪峰与突发 CC 攻击:我用 Go 写了个“现场物理防御哨兵”,把故障响应压缩到秒级
开发语言·后端·golang·报警灯
全麦面包 time展天17 小时前
瀚海拾贝(一)HTTP协议/IIS 原理及ASP.NET运行机制浅析【图解】
网络协议·http·asp.net
朋克洛德的码农20 小时前
反射是什么?
golang
2501_916008891 天前
移动安全之 APP 加固,保障移动应用安全的重要手段
安全·macos·ios·小程序·uni-app·iphone·xcode