惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
L
LangChain Blog
Jina AI
Jina AI
WordPress大学
WordPress大学
人人都是产品经理
人人都是产品经理
S
Secure Thoughts
T
The Exploit Database - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 聂微东
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
C
Cyber Attacks, Cyber Crime and Cyber Security
Project Zero
Project Zero
T
Threat Research - Cisco Blogs
量子位
G
GRAHAM CLULEY
腾讯CDC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
CERT Recently Published Vulnerability Notes
The Hacker News
The Hacker News
C
Cisco Blogs
Scott Helme
Scott Helme
Spread Privacy
Spread Privacy
宝玉的分享
宝玉的分享
V
V2EX
博客园 - 三生石上(FineUI控件)
T
Tor Project blog
P
Proofpoint News Feed
雷峰网
雷峰网
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Vulnerabilities – Threatpost
PCI Perspectives
PCI Perspectives
博客园_首页
L
LINUX DO - 最新话题
IT之家
IT之家
有赞技术团队
有赞技术团队
博客园 - Franky
Hacker News: Ask HN
Hacker News: Ask HN
Last Week in AI
Last Week in AI
The Cloudflare Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
美团技术团队
博客园 - 【当耐特】
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Security Archives - TechRepublic
Security Archives - TechRepublic
L
LINUX DO - 热门话题
AWS News Blog
AWS News Blog
S
Security Affairs
T
Tailwind CSS Blog

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw 第07章:参数化表达式与Spreadsheet 第08章:装配设计Assembly 第06章:Part工作台与几何内核 第05章:PartDesign实体特征建模 第04章:草图Sketcher约束建模 第02章:安装版本与工作环境配置 第03章:界面工作台与基础操作 第01章:项目全景与学习路线 第十二章:插件开发、研究功能与最佳实践 第十章:定时任务与自动化(Cron) 第七章:技能、记忆与自学习闭环 第八章:MCP 集成与上下文文件 第六章:工具系统与终端后端 第五章:模型供应商与配置体系 Hermes Agent 教程目录 第十一章:语音、视觉、浏览器与子代理协作 第四章:CLI/TUI 与会话管理 第十二章:学习路线、实战方案与最佳实践 第十一章:源码结构、开发调试与插件开发 第十章:自动化、远程访问、日志与排障 第九章:Control UI、节点、Canvas 与语音能力 第七章:工具、技能、插件与能力扩展 第八章:安全模型、访问控制与沙箱实践 第六章:Agent 工作区、会话与多智能体路由 第五章:多通道消息接入与聊天平台配置 第四章:配置体系、模型接入与认证管理 第三章:Gateway 架构、协议与运行机制 第二章:安装、环境准备与快速上手 第一章:OpenClaw 项目概览与核心定位 oh-my-openagent 教程目录 09-命令模型回退与配置参考 10-实战案例最佳实践与故障排除 05-工作模式-Ultrawork-Prometheus-Atlas 08-Hooks与MCP系统 06-Category与Skill系统 07-核心工具链 04-智能体全景详解 03-安装与环境配置 02-整体架构与多模型编排机制 01-项目简介与核心理念 01-项目概览与学习路线 02-安装部署与工具适配 03-Skill机制与using-superpowers 05-TDD系统化调试与完成前验证 04-需求澄清方案设计与计划编写 07-并行智能体子智能体与Git-Worktree 第六章:代码审查、反馈处理与分支收尾 08-中国特色Skills与本土团队落地 09-MCP构建工作流执行与自定义Skill 第23章:FreeCAD-Python-API Clipper2 C# 源码解读教程 第19章:PolyTree 多边形树结构 第20章:实际应用与最佳实践 第18章:Minkowski 和与差 第17章:RectClip 矩形裁剪优化 第16章:ClipperOffset 偏移类详解 第15章:填充规则详解 第14章:布尔运算执行流程 第13章:ClipperD 浮点裁剪类 第11章:OutRec 与 OutPt 输出结构 第9章:Active 活动边结构 第10章:Vertex 顶点与 LocalMinima 局部极小值 第12章:Clipper64 裁剪类详解 第7章:高精度运算与128位整数 第8章:ClipperBase 基类详解 第5章:枚举类型与常量定义 第6章:InternalClipper 内部工具类 第2章:核心数据结构 - Point64、PointD 第3章:路径与多边形表示 - Path64、PathD、Paths64、PathsD 第4章:矩形边界 - Rect64、RectD
第15章 - Web开发与net/http
我才是银古 · 2026-06-19 · via 博客园 - 我才是银古

第15章 - Web开发与net/http

Go 凭借出色的并发能力和强大的标准库,成为后端 Web 开发的热门选择。本章讲解使用标准库 net/http 构建 Web 服务的完整流程,并介绍主流 Web 框架。

15.1 最简 HTTP 服务器

Go 仅用几行代码即可启动一个生产可用的 HTTP 服务器:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, World!")
    })

    fmt.Println("服务器启动在 :8080")
    http.ListenAndServe(":8080", nil)
}
  • http.HandleFunc:注册一个路由及其处理函数。
  • http.ResponseWriter:用于写响应。
  • *http.Request:封装了请求的所有信息。
  • http.ListenAndServe:在指定端口启动服务,nil 表示使用默认的多路复用器。

15.2 处理器与处理函数

Go HTTP 服务的核心抽象是 http.Handler 接口:

type Handler interface {
    ServeHTTP(w http.ResponseWriter, r *http.Request)
}

任何实现了 ServeHTTP 方法的类型都是处理器。http.HandlerFunc 是一个适配器,能将普通函数转为 Handler:

type greetHandler struct {
    greeting string
}

func (h greetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%s!", h.greeting)
}

http.Handle("/greet", greetHandler{greeting: "你好"})

15.3 路由与多路复用器

http.ServeMux 是请求多路复用器,根据 URL 路径将请求分发到对应处理器:

mux := http.NewServeMux()
mux.HandleFunc("/users", usersHandler)
mux.HandleFunc("/products", productsHandler)
http.ListenAndServe(":8080", mux)

15.3.1 Go 1.22 增强路由

Go 1.22 大幅增强了标准库路由,支持方法匹配和路径参数,许多场景下不再需要第三方路由库:

mux := http.NewServeMux()

// 限定 HTTP 方法
mux.HandleFunc("GET /users", listUsers)
mux.HandleFunc("POST /users", createUser)

// 路径参数
mux.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id") // 提取路径参数
    fmt.Fprintf(w, "用户 ID: %s", id)
})

15.4 读取请求数据

15.4.1 查询参数与表单

func handler(w http.ResponseWriter, r *http.Request) {
    // URL 查询参数 ?name=alice&age=30
    name := r.URL.Query().Get("name")

    // 表单数据(POST)
    r.ParseForm()
    email := r.FormValue("email")

    // 请求头
    contentType := r.Header.Get("Content-Type")

    // 路径与方法
    fmt.Println(r.Method, r.URL.Path)
}

15.4.2 读取请求体(JSON)

type CreateUserRequest struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

func createUser(w http.ResponseWriter, r *http.Request) {
    var req CreateUserRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        http.Error(w, "无效的请求体", http.StatusBadRequest)
        return
    }
    defer r.Body.Close()
    // 处理 req...
}

15.5 返回响应

15.5.1 返回 JSON

func getUser(w http.ResponseWriter, r *http.Request) {
    user := User{Name: "Alice", Age: 30}

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(user)
}

15.5.2 设置状态码与错误

http.Error(w, "资源未找到", http.StatusNotFound)       // 404
w.WriteHeader(http.StatusCreated)                       // 201

// 重定向
http.Redirect(w, r, "/login", http.StatusFound)

注意:必须在写入响应体之前调用 WriteHeader 和设置 Header,否则设置无效。

15.6 中间件

中间件是包裹处理器的函数,用于实现日志、认证、限流、CORS 等横切关注点。Go 中间件通常是"接收 Handler、返回 Handler"的函数:

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r) // 调用下一个处理器
        log.Printf("%s %s 耗时 %v", r.Method, r.URL.Path, time.Since(start))
    })
}

func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token := r.Header.Get("Authorization")
        if token == "" {
            http.Error(w, "未授权", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}

// 链式组合
handler := loggingMiddleware(authMiddleware(mux))
http.ListenAndServe(":8080", handler)

15.7 优雅关闭

生产服务需要支持优雅关闭:停止接收新请求,等待正在处理的请求完成后再退出:

func main() {
    srv := &http.Server{Addr: ":8080", Handler: mux}

    go func() {
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatal(err)
        }
    }()

    // 等待中断信号
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
    <-quit

    // 给正在处理的请求 10 秒完成时间
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("强制关闭:", err)
    }
    log.Println("服务器已优雅退出")
}

15.8 HTTP 客户端

net/http 同样提供强大的客户端能力:

// 简单 GET
resp, err := http.Get("https://api.example.com/users")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)

// 自定义请求
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "******")

// 带超时的客户端(生产环境必须设置超时)
client := &http.Client{Timeout: 10 * time.Second}
resp, err = client.Do(req)

重要:必须 defer resp.Body.Close(),否则会导致连接泄漏。生产环境务必为客户端设置超时。

15.9 模板渲染

标准库 html/template 用于安全地渲染 HTML(自动转义防止 XSS)。模板使用双花括号语法插入数据:

import "html/template"

const page = `<h1>{% raw %}{{ .Title }}{% endraw %}</h1>
<ul>
{% raw %}{{ range .Items }}{% endraw %}
  <li>{% raw %}{{ . }}{% endraw %}</li>
{% raw %}{{ end }}{% endraw %}
</ul>`

func handler(w http.ResponseWriter, r *http.Request) {
    tmpl := template.Must(template.New("page").Parse(page))
    data := struct {
        Title string
        Items []string
    }{
        Title: "待办清单",
        Items: []string{"学习 Go", "编写 Web 服务"},
    }
    tmpl.Execute(w, data)
}

html/template 会根据上下文自动转义,有效防御跨站脚本攻击(XSS)。如果只是生成纯文本(非 HTML),可使用 text/template

15.10 主流 Web 框架

虽然标准库已足够强大,但社区框架在路由、参数绑定、中间件生态上更便捷:

框架 特点
Gin 最流行,高性能,API 简洁,中间件丰富
Echo 高性能,功能全面,文档完善
Fiber 受 Express 启发,基于 fasthttp,极致性能
Chi 轻量,完全兼容标准库 http.Handler
Beego 全栈 MVC 框架,企业级功能完善

以 Gin 为例:

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/users/:id", func(c *gin.Context) {
        id := c.Param("id")
        c.JSON(200, gin.H{"id": id})
    })
    r.Run(":8080")
}

15.11 本章小结

本章讲解了使用 Go 标准库 net/http 构建 Web 服务的完整流程:路由(含 Go 1.22 增强)、请求解析、响应生成、中间件、优雅关闭、HTTP 客户端和模板渲染。Go 的标准库已能胜任绝大多数 Web 开发需求,而 Gin、Echo 等框架则在便利性上更进一步。掌握这些知识,你已具备开发生产级 Web 服务的能力。

下一章我们将学习 Go 的数据库编程。