Chapter 10 / 10

写出优秀技术文档

README 结构模板、API 文档规范、中文写作准则、版本策略与文档健康维护

为什么技术写作很难

技术写作的难点不在于 Markdown 语法,而在于如何组织信息,让读者能快速找到所需内容并理解。技术文档有一个独特的挑战:你对产品太熟悉,往往无法站在陌生人的角度思考"读者需要什么"。

知识诅咒(Curse of Knowledge)
一旦你掌握了某些知识,就很难想象不知道这些知识是什么感觉。写文档时,作者往往省略了对他们来说"显而易见"的步骤,但读者却卡在这里。解决方法:找实际的陌生人测试你的文档。
好文档的标准
一个完全陌生的程序员,看了你的 README,能在 10 分钟内让项目运行起来;能在 5 分钟内判断这个项目是否适合他的需求;在遇到问题时知道去哪里找帮助。

优秀 README 的结构与原则

README 是项目的"门面",是绝大多数人对你的项目的第一印象。一个好的 README 需要在 30 秒内回答三个问题:这是什么?解决什么问题?我如何使用它?

完整的 README 模板

# 项目名称

> 一句话精准描述:这个项目是什么解决什么问题面向谁。
> 例:"轻量级 Go HTTP 框架,专为微服务设计,零依赖,比 Gin 快 3x。"

[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Go Version](https://img.shields.io/badge/Go-1.21%2B-blue)](go.mod)
[![CI](https://github.com/user/repo/workflows/CI/badge.svg)](actions)
[![Coverage](https://codecov.io/gh/user/repo/branch/main/graph/badge.svg)](codecov)

## ✨ 功能特性

- **核心特性 1**:一句话说明价值
- **核心特性 2**:一句话说明价值
- **核心特性 3**:一句话说明价值

## 🚀 快速开始

### 安装

```bash
go get github.com/yourname/yourpackage
```

### 最简示例(Hello World)

```go
package main

import "github.com/yourname/yourpackage"

func main() {
    r := yourpackage.New()
    r.GET("/", func(c *yourpackage.Context) {
        c.JSON(200, map[string]string{"message": "Hello, World!"})
    })
    r.Run(":8080")
}
```

运行:`go run main.go`,访问 `http://localhost:8080`。

## 📖 文档

- [完整文档](https://docs.example.com)
- [API 参考](https://pkg.go.dev/github.com/yourname/yourpackage)
- [示例代码](./examples/)
- [迁移指南](./MIGRATION.md)

## 🆚 与同类项目对比

| 特性         | 本项目  | Gin    | Echo   |
| ------------ | :-----: | :----: | :----: |
| 零依赖       | ✅      | ❌     | ❌     |
| 内存占用     | 8MB     | 12MB   | 10MB   |
| 每秒请求数   | 120k    | 78k    | 95k    |
| 学习曲线     | 低      | 低     | 中     |

## 🤝 贡献

欢迎 PR 和 Issue!请先阅读 [贡献指南](CONTRIBUTING.md)。

<details>
<summary>本地开发环境设置</summary>

```bash
git clone https://github.com/yourname/yourpackage
cd yourpackage
go test ./...        # 运行测试
go run ./cmd/main.go # 运行示例
```

</details>

## 许可证

MIT License — 详见 [LICENSE](LICENSE) 文件。

README 的关键原则

应该包含的内容

  • 一句话描述(精准,不废话)
  • 快速开始(可运行的示例)
  • 安装方法(多种包管理器)
  • 核心使用示例
  • 文档/API 参考链接
  • 贡献指南
  • 许可证

应该避免的内容

  • 冗长的项目历史背景
  • 过度的自我宣传
  • 所有功能的完整列表(放 docs 里)
  • 过时的截图(随版本更新困难)
  • 不会有人阅读的长段介绍

API 文档的标准结构

API 文档(函数、类、HTTP 端点)应该有一致的结构,让读者能快速找到他们需要的信息。

HTTP API 端点文档模板

## `POST /api/users` — 创建用户

创建一个新的用户账户。需要管理员权限。

### 请求头

| 字段            | 类型     | 必填 | 说明                            |
| --------------- | -------- | :--: | ------------------------------- |
| `Authorization` | `string` |  ✅  | Bearer 格式的 JWT Token         |
| `Content-Type`  | `string` |  ✅  | 必须为 `application/json`       |

### 请求体

```json
{
  "email": "user@example.com",       // 用户邮箱(唯一)
  "name": "张三",                    // 显示名称(2-50 字符)
  "role": "editor",                  // 可选:admin | editor | viewer(默认 viewer)
  "send_welcome_email": true         // 可选:是否发送欢迎邮件(默认 false)
}
```

### 响应

**成功(201 Created):**

```json
{
  "id": "usr_12345abc",
  "email": "user@example.com",
  "name": "张三",
  "role": "editor",
  "created_at": "2026-03-26T08:00:00Z"
}
```

**错误码:**

| 状态码 | 错误码              | 说明                         |
| ------ | ------------------- | ---------------------------- |
| `400`  | `invalid_email`     | 邮箱格式无效                 |
| `409`  | `email_exists`      | 该邮箱已注册                 |
| `401`  | `unauthorized`      | 未提供或 Token 无效          |
| `403`  | `forbidden`         | 当前用户无管理员权限         |

### 示例

```bash
curl -X POST https://api.example.com/api/users \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email":"new@example.com","name":"李四","role":"editor"}'
```

```javascript
// JavaScript SDK
const user = await client.users.create({
  email: "new@example.com",
  name: "李四",
  role: "editor"
});
```

函数/方法文档模板

### `getUserById(id, options?)`

根据用户 ID 查询用户信息。优先读取缓存,缓存未命中时查询数据库。

#### 参数

| 参数               | 类型     | 必填 | 说明                                        |
| ------------------ | -------- | :--: | ------------------------------------------- |
| `id`               | `string` |  ✅  | 用户唯一标识符(格式:`usr_` 前缀)          |
| `options.timeout`  | `number` |  ❌  | 超时毫秒数(默认 5000)                     |
| `options.useCache` | `boolean`|  ❌  | 是否使用缓存(默认 true)                   |

#### 返回值

返回 `Promise<User>`:

```typescript
interface User {
  id: string;        // 用户 ID
  email: string;     // 邮箱地址
  name: string;      // 显示名称
  role: UserRole;    // 用户角色
  createdAt: Date;   // 创建时间
}
```

#### 异常

- `UserNotFoundError`:用户 ID 不存在时抛出
- `TimeoutError`:超过 timeout 时间后抛出
- `DatabaseError`:数据库连接失败时抛出

#### 示例

```typescript
// 基本用法
const user = await getUserById("usr_12345");
console.log(user.name); // "张三"

// 设置超时
try {
  const user = await getUserById("usr_12345", { timeout: 2000 });
} catch (e) {
  if (e instanceof UserNotFoundError) {
    console.log("用户不存在");
  }
}

// 跳过缓存(强制数据库查询)
const freshUser = await getUserById("usr_12345", { useCache: false });
```

中文技术写作规范

中文技术文档有一套约定俗成的规范,遵循这些规范能显著提升文档的专业感和可读性。

中英文混排规范

# ✅ 正确:中英文之间加空格
使用 JavaScript 开发前端界面。
Python 3.10 以上版本需要安装 numpy 1.24+。
这是一个用 React 和 TypeScript 构建的项目。

# ❌ 错误:中英文紧贴
使用JavaScript开发前端界面。
Python3.10以上版本需要安装numpy1.24+。
INFO("盘古之白"原则)这个规范称为"盘古之白"(Pangu Spacing),得名于为汉字和拉丁字母之间保留空隙的中文排版规范。可以用 pangu.js 或其他语言实现自动添加空格,也有 VS Code 插件在输入时自动添加。

标点符号规范

场景✅ 正确❌ 错误
中文句末使用全角句号。使用半角句号.
代码和命令运行 `npm install`,完成后...运行`npm install`,完成后...
括号(中文括号)用于中文语境(中文语境用英文括号)
引号"中文引号" 用于中文"英文引号" 用于中文
专有名词macOS、iOS、GitHub、JavaScriptMacOS、IOS、Github、Javascript
中文数字共 10 个步骤共10个步骤(中文旁边加空格)

技术术语的一致性

# 在文档开头或首次出现时明确术语
本文档中,**构建(Build)**指将源代码编译为可执行文件的过程;
**部署(Deploy)**指将可执行文件发布到服务器的过程。

# 之后保持一致,不要混用同义词
# ❌ 错误:前面说"构建",后面突然变成"编译"
# ✅ 正确:整篇文章统一使用"构建"

段落和句子长度

文档的四种类型(Divio 文档系统)

Divio 公司提出了一个著名的文档分类框架,将技术文档分为四类,每类有不同的目标和写法:

教程(Tutorial)
面向初学者,通过完成一个真实项目来学习。目标:让读者成功运行起来并产生成就感。关键原则:每一步都有明确的结果,读者不需要理解原理就能跟着做。例:Django 官方教程"创建你的第一个投票应用"。
操作指南(How-to Guide)
面向有基础的用户,解决特定任务。目标:让用户完成一个具体目标。关键原则:假设读者已有基础知识,直接给出步骤。例:"如何在 Django 中实现自定义认证"。
参考文档(Reference)
完整的技术规格说明(API 参考、配置项说明)。目标:提供准确完整的信息,供查阅使用。关键原则:完整、精确、结构一致,通常不需要叙述性文字。
解释/概念(Explanation)
深入的概念讲解,帮助读者理解"为什么"。目标:建立理解,而不是完成任务。例:"Django 的 ORM 如何工作"、"JWT vs Session 认证的权衡"。
TIP大多数技术文档的问题在于混淆了这四类文档。教程中加入了太多概念解释(本应是 Explanation),API 参考中写了操作步骤(本应是 How-to)。清晰区分这四类,分别写对应的文档,读者体验会大幅提升。

版本化文档策略

在文档中标注版本信息

# 在 README 顶部标注适用版本

> **版本说明**:本文档适用于 v2.x。
> 如果你使用 v1.x,请查阅 [v1.x 文档](./docs/v1/)。

# 在特定章节标注版本

> **从 v2.3 起可用。** 此功能在早期版本不存在。

# 用 GFM 告警块标注废弃内容
> [!WARNING]
> **已废弃(v2.0 移除)**:`oldMethod()` 在 v2.0 中已移除,
> 请使用 [`newMethod()`](#new-method) 替代。

CHANGELOG 的标准格式

使用 Keep a Changelog 规范和 语义化版本(Semver):

# 更新日志

所有重要的更改都会记录在此文件中。
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。

## [未发布]

### 新增
- 用户个人资料页面支持上传头像

## [2.1.0] - 2026-03-26

### 新增
- 支持 OAuth2 第三方登录(GitHub、Google)
- 新增批量导入用户 API

### 变更
- 提升密码加密强度(bcrypt 从 10 轮升级到 12 轮)

### 修复
- 修复大文件上传时的内存泄漏问题(#234)
- 修复 Safari 下表单提交失败的 bug(#241)

### 废弃
- `User.getProfile()` 已废弃,将在 3.0 中移除,
  请使用 `User.profile` 属性替代

## [2.0.0] - 2026-01-15

### 破坏性变更(Breaking Changes)
- `createUser(name, email)` 签名变更为 `createUser(options: CreateUserOptions)`
- 移除对 Node.js 16 的支持,最低版本要求 Node.js 18

[未发布]: https://github.com/user/repo/compare/v2.1.0...HEAD
[2.1.0]: https://github.com/user/repo/compare/v2.0.0...v2.1.0
[2.0.0]: https://github.com/user/repo/compare/v1.5.0...v2.0.0

文档健康维护

文档不是一次性工作,需要持续维护。未更新的文档比没有文档更糟糕,因为它会误导读者。

文档腐烂(Documentation Rot)的预防

文档代码化(Docs as Code)
将文档存储在代码仓库中(与代码并排),每次代码变更时更新对应文档,作为 PR 的一部分进行 review。GitHub 会在 PR 中显示 Markdown 文件的变更 diff,和代码 diff 一样清晰。
代码示例的自动化测试
文档中的代码示例应该是可以运行的真实代码,而不是伪代码。最佳实践是将示例代码提取到可执行文件中(如 examples/ 目录),在 CI 中运行这些示例,确保示例随 API 变化一起更新。
定期链接检查
外部链接会随时间失效。使用 markdown-link-check 或 GitHub Actions 定期检查所有链接,修复死链。建议在 CI 中设置每周或每月的定时检查。

文档质量检查清单

## 新功能文档 PR 检查清单

- [ ] README 已更新(如果有影响 README 的变化)
- [ ] CHANGELOG 已更新
- [ ] API 文档已更新(新增/修改/删除的 API)
- [ ] 代码示例可以正常运行
- [ ] 代码示例的注释是最新的
- [ ] 废弃的功能已添加废弃警告
- [ ] 如有破坏性变更,已添加迁移指南
- [ ] 文档中的链接都有效
- [ ] 中英文混排规范符合要求

写给技术写作初学者的建议

从小处做起

参考优秀文档

多读好的技术文档,学习他们如何组织信息:

写作即思考

写文档不只是"把已知的东西记录下来",写作过程本身会帮助你发现设计中的问题:如果你发现某个功能很难解释清楚,往往意味着这个功能的设计不够好,或者 API 不够直观。

写作建议开始写一篇新文档之前,先问自己:这篇文档的读者是谁?他们的知识背景是什么?他们来这里是为了解决什么问题?有了清晰的目标读者,才能写出真正有用的文档。

课程总结

恭喜完成 Markdown 完全指南!你现在系统掌握了:

语法基础(第1-8章)

  • 标题、段落、文本格式
  • 列表(无序/有序/任务)
  • 链接、图片、徽章
  • 代码块与语法高亮
  • 引用块、分隔线、HTML
  • 表格(GFM 扩展)
  • Mermaid 图表(6种类型)
  • LaTeX 数学公式

工程实践(第9-10章)

  • VS Code 配置与插件
  • Typora / Obsidian 使用
  • Pandoc 格式转换
  • MkDocs / Docusaurus 文档站
  • markdownlint / Prettier 质量工具
  • README 结构模板
  • API 文档规范
  • 中文写作规范
  • CHANGELOG 最佳实践
下一步学了这么多,最重要的是实践。现在就去打开你的一个项目,把 README 改写一遍——按照本章的模板,加上清晰的描述、可运行的示例、正确的徽章。你会发现,用好 Markdown 真的能让你的项目更受欢迎。