doc-generate/README.md

885 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# go-doc
[![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.23-blue)](https://go.dev/)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Version](https://img.shields.io/badge/version-1.2.0-blue)](CHANGELOG.md)
**go-doc** 是一個獨立的命令行工具,專門用於將 [go-zero](https://github.com/zeromicro/go-zero) `.api` 文件轉換為 OpenAPI 規範文檔。
原本是 go-zero 專案的一部分,現在已獨立出來,成為一個易於使用的工具,支援生成 **Swagger 2.0****OpenAPI 3.0** 兩種格式。
---
## 📑 目錄
- [✨ 特性](#-特性)
- [📦 安裝](#-安裝)
- [🚀 快速開始](#-快速開始)
- [📖 API 文件格式](#-api-文件格式)
- [🆕 @respdoc 多狀態碼回應](#-respdoc-多狀態碼回應)
- [🔧 進階功能](#-進階功能)
- [🎯 OpenAPI 3.0 vs Swagger 2.0](#-openapi-30-vs-swagger-20)
- [💡 使用範例](#-使用範例)
- [🧪 測試](#-測試)
- [📚 專案結構](#-專案結構)
- [🔄 從 go-zero 遷移](#-從-go-zero-遷移)
- [📝 版本記錄](#-版本記錄)
- [❓ 常見問題](#-常見問題)
- [🤝 貢獻](#-貢獻)
- [📄 授權](#-授權)
---
## ✨ 特性
- 🚀 **獨立二進制** - 無需依賴 go-zero 運行時
- 📝 **雙規格支援** - 生成 **Swagger 2.0****OpenAPI 3.0** 格式
- 🎯 **豐富的類型支援** - 處理結構體、陣列、映射、指針和嵌套類型
- 🏷️ **基於標籤的配置** - 支援 `json`、`form`、`path`、`header` 標籤
- 📊 **進階驗證** - 範圍、枚舉、預設值、範例值
- 🔐 **安全定義** - 自定義身份驗證配置
- 📦 **多種輸出格式** - JSON 或 YAML 輸出
- 🎨 **定義引用** - 可選使用 definitions/schemas 使輸出更簡潔
- 🔄 **自動轉換** - Swagger 2.0 到 OpenAPI 3.0 的無縫轉換
- **🆕 多狀態碼回應** - 使用 `@respdoc` 定義多個 HTTP 狀態碼
- **🆕 業務錯誤碼映射** - 將業務錯誤碼映射到不同的錯誤類型OpenAPI 3.0 使用 `oneOf`
---
## 📦 安裝
### 從源碼編譯
```bash
git clone <your-repo>
cd go-doc
make build
```
編譯完成後,執行檔位於 `bin/go-doc`
### 使用 Go Install
```bash
go install github.com/danielchan-25/go-doc/cmd/go-doc@latest
```
---
## 🚀 快速開始
### 基本使用
```bash
# 生成 Swagger 2.0(預設)
go-doc -a example/example.api -d output
# 生成 OpenAPI 3.0(推薦)
go-doc -a example/example.api -d output -s openapi3.0
# 生成 YAML 格式
go-doc -a example/example.api -d output -y
# 生成 OpenAPI 3.0 YAML
go-doc -a example/example.api -d output -s openapi3.0 -y
# 自訂檔名
go-doc -a example/example.api -d output -f my-api
```
### 命令行選項
```
Flags:
-a, --api string API 文件路徑(必要)
-d, --dir string 輸出目錄(必要)
-f, --filename string 輸出檔名(不含副檔名)
-h, --help 顯示說明
-s, --spec-version string OpenAPI 規格版本swagger2.0 或 openapi3.0預設swagger2.0
-v, --version 顯示版本
-y, --yaml 生成 YAML 格式預設JSON
```
### 使用 Makefile
```bash
# 編譯
make build
# 生成範例
make example
# 清理
make clean
# 運行測試
make test
# 查看所有命令
make help
```
---
## 📖 API 文件格式
### 基本結構
```go
syntax = "v1"
info (
title: "My API"
description: "API documentation"
version: "v1.0.0"
host: "api.example.com"
basePath: "/v1"
)
type (
UserRequest {
Id int `json:"id,range=[1:10000]"`
Name string `json:"name"`
}
UserResponse {
Id int `json:"id"`
Name string `json:"name"`
}
)
@server (
tags: "user"
)
service MyAPI {
@handler getUser
get /user/:id (UserRequest) returns (UserResponse)
}
```
### 支援的 Info 屬性
- `title` - API 標題
- `description` - API 描述
- `version` - API 版本
- `host` - API 主機(如 "api.example.com"
- `basePath` - 基礎路徑(如 "/v1"
- `schemes` - 協議(如 "http,https"
- `consumes` - 請求內容類型
- `produces` - 回應內容類型
- `contactName`, `contactURL`, `contactEmail` - 聯絡資訊
- `licenseName`, `licenseURL` - 授權資訊
- `useDefinitions` - 使用 Swagger definitionstrue/false
- `wrapCodeMsg` - 將回應包裝在 `{code, msg, data}` 結構中
- `securityDefinitionsFromJson` - JSON 格式的安全定義
### 標籤選項
#### JSON 標籤
```go
type Example {
// 範圍驗證
Age int `json:"age,range=[1:150]"`
// 預設值
Status string `json:"status,default=active"`
// 範例值
Email string `json:"email,example=user@example.com"`
// 枚舉值
Role string `json:"role,options=admin|user|guest"`
// 可選欄位
Phone string `json:"phone,optional"`
}
```
#### Form 標籤
```go
type QueryRequest {
Keyword string `form:"keyword"`
Page int `form:"page,default=1"`
Size int `form:"size,range=[1:100]"`
}
```
#### Path 標籤
```go
type PathRequest {
UserId int `path:"userId,range=[1:999999]"`
}
```
#### Header 標籤
```go
type HeaderRequest {
Token string `header:"Authorization"`
}
```
---
## 🆕 @respdoc 多狀態碼回應
### 概述
`@respdoc` 註解允許您為單個 API 端點定義多個 HTTP 狀態碼的回應,並支援為同一狀態碼定義多種業務錯誤格式。
**重要特性:**
- ✅ 支援多個 HTTP 狀態碼200, 201, 400, 401, 404, 500 等)
- ✅ 支援業務錯誤碼映射(如 300101, 300102 等)
-**OpenAPI 3.0 使用 `oneOf` 表示多種錯誤格式**
- ✅ Swagger 2.0 在描述中列出所有可能的錯誤
### 基本語法
#### 單一回應類型
```go
service MyAPI {
@doc (
description: "用戶查詢接口"
)
/*
@respdoc-200 (UserResponse) // 成功
@respdoc-400 (ErrorResponse) // 錯誤請求
@respdoc-401 (UnauthorizedError) // 未授權
@respdoc-500 (ServerError) // 服務器錯誤
*/
@handler getUser
get /user/:id (UserRequest) returns (UserResponse)
}
```
#### 多業務錯誤碼(重點功能)⭐
```go
service MyAPI {
@doc (
description: "創建訂單"
)
/*
@respdoc-201 (OrderResponse) // 創建成功
@respdoc-400 (
300101: (ValidationError) 參數驗證失敗
300102: (InsufficientStockError) 庫存不足
300103: (InvalidPaymentError) 支付方式無效
) // 客戶端錯誤
@respdoc-401 (UnauthorizedError) // 未授權
@respdoc-500 (ServerError) // 服務器錯誤
*/
@handler createOrder
post /order (OrderRequest) returns (OrderResponse)
}
```
### 完整範例
```go
syntax = "v1"
info (
title: "訂單 API"
description: "訂單管理系統"
version: "v1"
host: "api.example.com"
basePath: "/v1"
useDefinitions: true
)
type (
CreateOrderReq {
ProductID string `json:"product_id"`
Quantity int `json:"quantity"`
PaymentMethod string `json:"payment_method"`
}
OrderResponse {
OrderID string `json:"order_id"`
Status string `json:"status"`
Total float64 `json:"total"`
}
ValidationError {
Code string `json:"code"`
Message string `json:"message"`
Fields []string `json:"fields"`
}
InsufficientStockError {
Code string `json:"code"`
Message string `json:"message"`
ProductID string `json:"product_id"`
Required int `json:"required"`
Available int `json:"available"`
}
InvalidPaymentError {
Code string `json:"code"`
Message string `json:"message"`
Method string `json:"method"`
}
UnauthorizedError {
Code string `json:"code"`
Message string `json:"message"`
Reason string `json:"reason"`
}
ServerError {
Code string `json:"code"`
Message string `json:"message"`
TraceID string `json:"trace_id"`
}
)
@server (
tags: "order"
)
service OrderAPI {
@doc (
description: "創建訂單"
)
/*
@respdoc-201 (OrderResponse) // 創建成功
@respdoc-400 (
300101: (ValidationError) 參數驗證失敗
300102: (InsufficientStockError) 庫存不足
300103: (InvalidPaymentError) 支付方式無效
) // 客戶端錯誤
@respdoc-401 (UnauthorizedError) // 未授權
@respdoc-500 (ServerError) // 服務器錯誤
*/
@handler createOrder
post /order (CreateOrderReq) returns (OrderResponse)
}
```
### 生成結果對比
#### Swagger 2.0 輸出
```json
{
"paths": {
"/v1/order": {
"post": {
"responses": {
"201": {
"description": "// 創建成功",
"schema": {
"$ref": "#/definitions/OrderResponse"
}
},
"400": {
"description": "客戶端錯誤\n\nPossible errors:\n300101: ValidationError - 參數驗證失敗\n300102: InsufficientStockError - 庫存不足\n300103: InvalidPaymentError - 支付方式無效",
"schema": {
"$ref": "#/definitions/ValidationError"
}
}
}
}
}
}
}
```
#### OpenAPI 3.0 輸出(使用 oneOf
```json
{
"paths": {
"/v1/order": {
"post": {
"responses": {
"201": {
"description": "// 創建成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrderResponse"
}
}
}
},
"400": {
"description": "客戶端錯誤",
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"$ref": "#/components/schemas/ValidationError"
},
{
"$ref": "#/components/schemas/InsufficientStockError"
},
{
"$ref": "#/components/schemas/InvalidPaymentError"
}
]
}
}
}
}
}
}
}
}
}
```
**優勢:** OpenAPI 3.0 使用 `oneOf` 精確表示多種可能的錯誤類型!
---
## 🔧 進階功能
### 安全定義
```go
info (
securityDefinitionsFromJson: `{
"apiKey": {
"type": "apiKey",
"name": "x-api-key",
"in": "header",
"description": "API Key Authentication"
}
}`
)
@server (
authType: apiKey
)
service MyAPI {
// 此處的路由將使用 apiKey 身份驗證
}
```
### Code-Msg 包裝
```go
info (
wrapCodeMsg: true
bizCodeEnumDescription: "1001-User not found<br>1002-Permission denied"
)
```
回應將被包裝為:
```json
{
"code": 0,
"msg": "ok",
"data": { /* your actual response */ }
}
```
---
## 🎯 OpenAPI 3.0 vs Swagger 2.0
### 規格版本
#### Swagger 2.0(預設)
```bash
go-doc -a example/example.api -d output
# 或明確指定
go-doc -a example/example.api -d output -s swagger2.0
```
#### OpenAPI 3.0(推薦)
```bash
go-doc -a example/example.api -d output -s openapi3.0
```
### 主要差異
| 特性 | Swagger 2.0 | OpenAPI 3.0 |
|:---|:---|:---|
| **版本聲明** | `swagger: "2.0"` | `openapi: "3.0.3"` |
| **服務器** | `host`, `basePath`, `schemes` | `servers` 陣列 |
| **Schema 定義** | `definitions` | `components/schemas` |
| **安全定義** | `securityDefinitions` | `components/securitySchemes` |
| **請求體** | `parameters[in=body]` | `requestBody` |
| **多類型回應** | ❌ 不支援 | ✅ `oneOf`/`anyOf`/`allOf` |
### 範例對比
**Swagger 2.0:**
```json
{
"swagger": "2.0",
"host": "example.com",
"basePath": "/v1",
"definitions": {
"User": {...}
},
"securityDefinitions": {
"apiKey": {...}
}
}
```
**OpenAPI 3.0:**
```json
{
"openapi": "3.0.3",
"servers": [
{"url": "http://example.com/v1"},
{"url": "https://example.com/v1"}
],
"components": {
"schemas": {
"User": {...}
},
"securitySchemes": {
"apiKey": {...}
}
}
}
```
---
## 💡 使用範例
### 場景 1RESTful CRUD
```go
/*
@respdoc-200 (UserResponse) // 獲取成功
@respdoc-404 (NotFoundError) // 用戶不存在
@respdoc-401 (UnauthorizedError) // 未授權
*/
@handler getUser
get /user/:id (UserIdReq) returns (UserResponse)
/*
@respdoc-201 (UserResponse) // 創建成功
@respdoc-400 (ValidationError) // 參數錯誤
@respdoc-409 (ConflictError) // 用戶已存在
*/
@handler createUser
post /user (CreateUserReq) returns (UserResponse)
/*
@respdoc-200 (UserResponse) // 更新成功
@respdoc-400 (ValidationError) // 參數錯誤
@respdoc-404 (NotFoundError) // 用戶不存在
*/
@handler updateUser
put /user/:id (UpdateUserReq) returns (UserResponse)
/*
@respdoc-204 // 刪除成功
@respdoc-404 (NotFoundError) // 用戶不存在
*/
@handler deleteUser
delete /user/:id (UserIdReq)
```
### 場景 2複雜業務流程
```go
/*
@respdoc-200 (PaymentResponse) // 支付成功
@respdoc-400 (
400001: (InsufficientBalanceError) 餘額不足
400002: (InvalidCardError) 無效的卡號
400003: (ExpiredCardError) 卡已過期
400004: (DailyLimitError) 超過每日限額
) // 支付失敗
@respdoc-401 (UnauthorizedError) // 未授權
@respdoc-422 (ProcessingError) // 處理中請勿重複提交
*/
@handler processPayment
post /payment (PaymentRequest) returns (PaymentResponse)
```
### 場景 3狀態機轉換
```go
/*
@respdoc-200 (OrderResponse) // 狀態更新成功
@respdoc-400 (
400001: (InvalidStateError) 無效的狀態轉換
400002: (OrderCancelledError) 訂單已取消
400003: (OrderCompletedError) 訂單已完成
) // 狀態轉換失敗
*/
@handler updateOrderStatus
put /order/:id/status (UpdateStatusReq) returns (OrderResponse)
```
---
## 🧪 測試
### 測試所有格式
```bash
# 測試 Swagger 2.0 和 OpenAPI 3.0
./test_all_formats.sh
# 測試 @respdoc 功能
./test_respdoc.sh
```
### 手動測試
```bash
# 生成並檢查
go-doc -a example/example_respdoc.api -d output -s openapi3.0
# 查看生成的文檔
cat output/example_respdoc.json | jq '.paths."/v1/order".post.responses'
```
---
## 📚 專案結構
```
go-doc/
├── cmd/
│ └── go-doc/ # 主程式入口
│ └── main.go
├── internal/
│ ├── swagger/ # 核心邏輯
│ │ ├── respdoc.go # @respdoc 解析
│ │ ├── response.go # 回應生成
│ │ ├── openapi3.go # OpenAPI 3.0 轉換
│ │ ├── swagger.go # Swagger 2.0 生成
│ │ ├── path.go # 路徑處理
│ │ ├── parameter.go # 參數處理
│ │ ├── definition.go # 定義處理
│ │ └── ...
│ └── util/ # 工具函數
│ ├── util.go
│ ├── stringx.go
│ └── pathx.go
├── example/
│ ├── example.api # 範例 API
│ ├── example_cn.api # 中文範例
│ ├── example_respdoc.api # @respdoc 範例
│ └── test_output/ # 生成的文檔
├── bin/ # 編譯後的執行檔
├── go.mod
├── go.sum
├── Makefile
├── README.md
├── LICENSE
├── CHANGELOG.md
├── test_all_formats.sh # 測試腳本
└── test_respdoc.sh # @respdoc 測試
```
---
## 🔄 從 go-zero 遷移
### 主要變更
#### 1. 模組獨立
**之前go-zero plugin:**
```go
// 屬於 go-zero 內部工具
package swagger // in tools/goctl/api/plugin/swagger/
```
**現在standalone:**
```go
module go-doc
package swagger // in internal/swagger/
```
#### 2. 依賴簡化
| 依賴 | 替換為 | 原因 |
|:---|:---|:---|
| `go-zero/tools/goctl/internal/version` | 自定義版本 | 內部包不可訪問 |
| `go-zero/tools/goctl/util` | `go-doc/internal/util` | 自包含工具 |
| `go-zero/tools/goctl/util/stringx` | `go-doc/internal/util` | 自定義字串處理 |
| `go-zero/tools/goctl/util/pathx` | `go-doc/internal/util` | 自定義路徑處理 |
| `google.golang.org/grpc/metadata` | 原生 map 處理 | 移除外部依賴 |
#### 3. 保留的依賴
-`github.com/go-openapi/spec` - Swagger 2.0
-`github.com/getkin/kin-openapi` - OpenAPI 3.0
-`github.com/spf13/cobra` - CLI 框架
-`github.com/zeromicro/go-zero/tools/goctl/api/spec` - API 解析
-`gopkg.in/yaml.v2` - YAML 支援
### 遷移步驟
1. **安裝 go-doc**
```bash
go build -o bin/go-doc ./cmd/go-doc
```
2. **替換命令**
**之前:**
```bash
goctl api plugin -plugin goctl-swagger="swagger -filename api.json" -api user.api -dir .
```
**現在:**
```bash
go-doc -a user.api -d . -f api
```
3. **新功能**
使用 OpenAPI 3.0
```bash
go-doc -a user.api -d . -f api -s openapi3.0
```
使用 @respdoc
```go
/*
@respdoc-200 (Response) // 成功
@respdoc-400 (Error) // 錯誤
*/
```
---
## 📝 版本記錄
### [1.2.0] - 2025-09-30
#### 新增
- **@respdoc 註解支援** - 為單個端點定義多個 HTTP 狀態碼
- **業務錯誤碼映射** - 將不同的業務錯誤碼映射到特定錯誤類型
- **OpenAPI 3.0 oneOf 支援** - 使用 `oneOf` 表示多種可能的錯誤回應
- 測試腳本 `test_respdoc.sh`
- 支援解析 `HandlerDoc` 註釋(在 `@doc()` 外)
#### 增強
- 回應生成現在支援多個狀態碼200, 201, 400, 401, 404, 500 等)
- OpenAPI 3.0 生成器為業務錯誤碼創建 `oneOf` schema
- Swagger 2.0 在描述中列出所有可能的錯誤
### [1.1.0] - 2025-09-30
#### 新增
- **OpenAPI 3.0 支援** - 生成 Swagger 2.0 和 OpenAPI 3.0 規格
- 新增 `--spec-version` (`-s`) 標誌
- 自動從 Swagger 2.0 轉換到 OpenAPI 3.0
- 整合 `github.com/getkin/kin-openapi` 函式庫
### [1.0.0] - 2025-09-30
#### 新增
- 初始發布為獨立工具
- 從 go-zero 專案提取並獨立
- 支援將 go-zero `.api` 文件轉換為 Swagger 2.0 規格
- JSON 和 YAML 輸出格式
- 使用 cobra 的命令行介面
---
## ❓ 常見問題
### Q: 應該使用哪個版本?
**A:**
- **Swagger 2.0**: 如果需要與舊工具或系統相容
- **OpenAPI 3.0**: 推薦使用,功能更強大且為現代標準
### Q: 為什麼 OpenAPI 3.0 使用 oneOf
**A:** `oneOf` 是 OpenAPI 3.0 的標準方式來表示"多選一"的 schema。這讓 API 文檔更精確,工具(如 Swagger UI、代碼生成器可以正確理解和處理多種可能的回應類型。
### Q: Swagger 2.0 為什麼不支援 oneOf
**A:** Swagger 2.0 規範不包含 `oneOf` 關鍵字。我們在描述中列出所有可能的錯誤,並使用第一個類型作為 schema 示例。
### Q: 可以同時生成兩種格式嗎?
**A:** 可以!執行兩次命令即可:
```bash
go-doc -a api.api -d out -f api-v2
go-doc -a api.api -d out -f api-v3 -s openapi3.0
```
### Q: 可以不定義業務錯誤碼嗎?
**A:** 可以!如果只有一種錯誤類型,直接使用單一回應格式:
```go
@respdoc-400 (ValidationError) // 參數錯誤
```
### Q: 如何驗證生成的文檔?
**A:** 可以使用以下工具:
- **Swagger Editor**: https://editor.swagger.io/
- **Swagger UI**: 本地運行或線上版本
- **OpenAPI Generator**: 生成客戶端/伺服器代碼來驗證
---
## 🤝 貢獻
歡迎貢獻!請隨時提交 Pull Request。
### 開發
```bash
# 克隆專案
git clone <your-repo>
cd go-doc
# 安裝依賴
go mod download
# 運行測試
make test
# 編譯
make build
# 運行範例
make example
```
---
## 📄 授權
MIT License
Copyright (c) 2025 Daniel Chan
本專案最初是 [go-zero](https://github.com/zeromicro/go-zero) 專案 swagger 生成插件的一部分。我們感謝 go-zero 團隊的出色工作。
---
## 🎉 總結
**go-doc v1.2.0** 提供了強大的 API 文檔生成功能:
**雙規格支援** - Swagger 2.0 和 OpenAPI 3.0
**多狀態碼回應** - 使用 @respdoc 定義完整的 HTTP 回應
**業務錯誤碼映射** - 支援複雜的錯誤場景
**OpenAPI 3.0 oneOf** - 專業的多類型回應表示
**完整測試** - 自動化測試腳本
**詳細文檔** - 完整的使用指南
開始使用:
```bash
go-doc -a your-api.api -d docs -s openapi3.0
```
查看範例:
- 基本範例:`example/example.api`
- @respdoc 範例:`example/example_respdoc.api`
- 測試腳本:`./test_respdoc.sh`
---
**🌟 如果這個專案對您有幫助,請給個 Star**