@vincent119/go-copilot-rules 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent_agy/INSTALLATION.md +786 -0
- package/.agent_agy/README.md +243 -0
- package/.agent_agy/SKILLS_INDEX.md +516 -0
- package/.agent_agy/rules/go-core.copilot-instructions.md +251 -0
- package/.agent_agy/skills/go-api-design/SKILL.md +535 -0
- package/.agent_agy/skills/go-ci-tooling/SKILL.md +533 -0
- package/.agent_agy/skills/go-configuration/SKILL.md +609 -0
- package/.agent_agy/skills/go-database/SKILL.md +412 -0
- package/.agent_agy/skills/go-ddd/SKILL.md +374 -0
- package/.agent_agy/skills/go-dependency-injection/SKILL.md +546 -0
- package/.agent_agy/skills/go-domain-events/SKILL.md +525 -0
- package/.agent_agy/skills/go-examples/SKILL.md +690 -0
- package/.agent_agy/skills/go-graceful-shutdown/SKILL.md +708 -0
- package/.agent_agy/skills/go-grpc/SKILL.md +484 -0
- package/.agent_agy/skills/go-http-advanced/SKILL.md +494 -0
- package/.agent_agy/skills/go-observability/SKILL.md +684 -0
- package/.agent_agy/skills/go-testing-advanced/SKILL.md +573 -0
- package/LICENSE +21 -0
- package/README.md +176 -0
- package/cli/install.js +344 -0
- package/package.json +47 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
trigger: always_on
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Go 核心開發規範(Always-On 精簡版)
|
|
6
|
+
|
|
7
|
+
本檔僅包含**所有 Go 程式碼都需要的基礎規則**。進階主題(DDD、gRPC、Migration 等)已拆分為獨立 Skills,按需載入。
|
|
8
|
+
|
|
9
|
+
> **參照標準**:[Uber Go 風格指南](https://github.com/ianchen0119/uber_go_guide_tw) | [Effective Go](https://go.dev/doc/effective_go)
|
|
10
|
+
> **Go 版本目標**:Go 1.25+
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Copilot / Agent 產生守則
|
|
15
|
+
|
|
16
|
+
### 檔案與 Package 規範
|
|
17
|
+
- 每檔僅 **一行** `package <name>` 宣告(置頂)
|
|
18
|
+
- 編輯檔案:保留原 package
|
|
19
|
+
- 新檔案:與資料夾既有 `.go` 同名 package
|
|
20
|
+
- 可執行程式置於 `cmd/<app>/main.go`,library 不得含 `main()`
|
|
21
|
+
- Package 名稱:**全小寫、單字、無底線**(避免 `util`、`common`)
|
|
22
|
+
|
|
23
|
+
### Imports 與工具
|
|
24
|
+
- 產出前必可通過 `gofmt -s`(建議 `gofumpt`)、`goimports`、`go vet`
|
|
25
|
+
- 自動清除未用 imports,避免循環依賴
|
|
26
|
+
- 變更 `go.mod` 後提示 `go mod tidy`
|
|
27
|
+
- 縮排:Tab;檔尾留 **單一** 換行;UTF-8(無 BOM)
|
|
28
|
+
- Imports 排序:**標準庫 → 第三方 → 專案內部**;群組以空行分隔
|
|
29
|
+
|
|
30
|
+
### 錯誤處理與流程
|
|
31
|
+
- 呼叫後**立即**檢查 `err`,採 **early return**
|
|
32
|
+
- 包裝錯誤:`fmt.Errorf("context: %w", err)`;跨層使用 `errors.Is/As`
|
|
33
|
+
- 多重錯誤聚合使用 `errors.Join`(如:驗證列表或 defer Close)
|
|
34
|
+
- 訊息小寫開頭,尾端**不加標點**
|
|
35
|
+
- 僅在**不可恢復初始化**時用 `panic`;避免在 library 使用
|
|
36
|
+
- 禁止「只記錄不回傳」導致錯誤吞沒;**記錄與回傳擇一**,以邏輯層級決定
|
|
37
|
+
|
|
38
|
+
### 函式設計
|
|
39
|
+
- 函式應該簡短且專注於單一任務(建議不超過 50 行)
|
|
40
|
+
- 參數數量盡量控制在 3-4 個以內
|
|
41
|
+
- 使用具名回傳值提高可讀性(但避免 naked return)
|
|
42
|
+
- `context.Context` 應該作為第一個參數
|
|
43
|
+
- `error` 應該作為最後一個回傳值
|
|
44
|
+
- 避免 `bool` 參數(改用具名 Option 或拆分函式)
|
|
45
|
+
- 多參數時採用 **Functional Options Pattern**(`opts ...Option`)提升擴展性
|
|
46
|
+
|
|
47
|
+
```go
|
|
48
|
+
// ✅ 正確:context 第一、error 最後、使用 Functional Options
|
|
49
|
+
func ProcessData(ctx context.Context, data []byte, opts ...Option) (Result, error)
|
|
50
|
+
|
|
51
|
+
// ✅ Functional Options Pattern 範例
|
|
52
|
+
type Option func(*config)
|
|
53
|
+
|
|
54
|
+
func WithTimeout(d time.Duration) Option {
|
|
55
|
+
return func(c *config) { c.timeout = d }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
func WithRetries(n int) Option {
|
|
59
|
+
return func(c *config) { c.retries = n }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ❌ 錯誤:bool 參數、context 不在第一個
|
|
63
|
+
func ProcessData(data []byte, timeout int, retries int, debug bool, ctx context.Context) (Result, error)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 並行與 I/O 安全
|
|
67
|
+
- 每個 goroutine 需有**退出機制**(`context`、`WaitGroup` 或關閉 channel)
|
|
68
|
+
- Channel 緩衝預設 0 或 1(除非有量測證據)
|
|
69
|
+
- 嚴禁 goroutine 泄漏;資源關閉要落在呼叫點 `defer Close()`
|
|
70
|
+
- 不可重用已讀取的 `req.Body`;需 **clone**:
|
|
71
|
+
```go
|
|
72
|
+
// 將來源位元組切片拷貝,確保可重播 Body
|
|
73
|
+
buf := bytes.Clone(src)
|
|
74
|
+
req.Body = io.NopCloser(bytes.NewReader(buf))
|
|
75
|
+
req.GetBody = func() (io.ReadCloser, error) {
|
|
76
|
+
return io.NopCloser(bytes.NewReader(buf)), nil
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
- `io.Pipe`/multipart 必須**單執行緒順序寫入**;失敗用 `pw.CloseWithError(err)`、成功 `mw.Close()` 再 `pw.Close()`
|
|
80
|
+
- 底層 slice/map 在**邊界(入/出)**時一律複製,避免別名共享
|
|
81
|
+
|
|
82
|
+
### JSON / Struct Tag
|
|
83
|
+
- 對外型別欄位加上 `json,yaml,mapstructure` tags;**選填**欄位 `omitempty`
|
|
84
|
+
- 輸入端(decode)預設**拒絕未知欄位**:
|
|
85
|
+
```go
|
|
86
|
+
dec := json.NewDecoder(r)
|
|
87
|
+
dec.DisallowUnknownFields()
|
|
88
|
+
```
|
|
89
|
+
- 使用 `any` 取代 `interface{}`;但優先具體型別
|
|
90
|
+
- 時間欄位採 **RFC3339**(UTC 優先);必要時標注本地時區偏差
|
|
91
|
+
|
|
92
|
+
### 測試基礎
|
|
93
|
+
- 採 **table-driven tests**;子測試用 `t.Run`
|
|
94
|
+
- 使用 `t.Context()` 獲取自動管理的 context(Go 1.24+;本專案目標 Go 1.25+ 故可直接採用)
|
|
95
|
+
- 輔助函式 `t.Helper()`;清理用 `t.Cleanup()`
|
|
96
|
+
- 匯出 API 提供 `example_test.go`
|
|
97
|
+
- 優先標準 `testing`;除非必要不引入 assert 套件
|
|
98
|
+
|
|
99
|
+
### 產出內容要求
|
|
100
|
+
- 輸出 **完整可編譯檔案**或明確 **diff**
|
|
101
|
+
- 多檔變更列出:檔名 / 變更摘要 / 風險
|
|
102
|
+
- 新增外部套件需附:`go get <module>@<version>` 與風險評估
|
|
103
|
+
|
|
104
|
+
### 詞彙與術語
|
|
105
|
+
- 優先 `.github/standards/copilot-vocabulary.yaml`
|
|
106
|
+
- 與現有命名衝突時以 vocabulary 為準
|
|
107
|
+
- 與 Uber/Effective Go 不一致時,PR **必述理由**與替代方案
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Go 一般開發規範
|
|
112
|
+
|
|
113
|
+
### 通用原則
|
|
114
|
+
- 清晰優於巧妙;主流程靠左排列;讓 **零值可用**
|
|
115
|
+
- 結構自我說明;註解描述「**為何**」而非「做什麼」
|
|
116
|
+
|
|
117
|
+
### 命名慣例
|
|
118
|
+
- Package:全小寫、單字、無底線;避免 `util`、`common`
|
|
119
|
+
- 變數/函式:小駝峰;匯出名稱首字母大寫
|
|
120
|
+
- 介面以 `-er` 結尾(Reader/Writer);**小介面**優先
|
|
121
|
+
- 縮略詞大小寫一致:`HTTPServer`、`URLParser`
|
|
122
|
+
- 建構子命名採 `NewType(...)`;必要時 `WithXxx` 選項,但避免過度抽象
|
|
123
|
+
- 常數使用駝峰式(匯出:`MaxRetryCount`;私有:`maxRetryCount`),**禁用全大寫底線**
|
|
124
|
+
|
|
125
|
+
### 常數與列舉
|
|
126
|
+
- 群組 `const (...)`;**型別化常數**避免魔數
|
|
127
|
+
- Enum 起始值**考慮零值可用性**,必要時保留 `Unknown`
|
|
128
|
+
|
|
129
|
+
### 接收者與方法
|
|
130
|
+
- 以量測決定**指標/值**接收者(大型結構/需變異 → 指標;小值/不變 → 值)
|
|
131
|
+
- 避免 `init()` 副作用與全域可變狀態
|
|
132
|
+
- 針對可能回傳大量數據的列表方法,優先使用 **Iterators** (`func(yield func(T) bool)`) (Go 1.23+) 取代 Slice 回傳
|
|
133
|
+
|
|
134
|
+
```go
|
|
135
|
+
// Iterator 範例:避免一次載入全部資料
|
|
136
|
+
func (s *Set[T]) Iterator() iter.Seq[T] {
|
|
137
|
+
return func(yield func(T) bool) {
|
|
138
|
+
for _, v := range s.values {
|
|
139
|
+
if !yield(v) {
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Context 規範
|
|
148
|
+
- 對外 API **第一個參數**為 `ctx context.Context`
|
|
149
|
+
- 禁用 `context.Background()` 直傳至深層;由呼叫者注入
|
|
150
|
+
- 設定逾時/截止於**呼叫邊界**;尊重 `ctx.Done()`
|
|
151
|
+
- 不將 `ctx` 保存於結構體
|
|
152
|
+
|
|
153
|
+
### 並行進階
|
|
154
|
+
- 以 `errgroup`/`WaitGroup` + `ctx` 收斂;提供**背壓**與**取消**
|
|
155
|
+
- 共享狀態以 `sync.Mutex/RWMutex` 或無鎖結構(經量測)保護
|
|
156
|
+
|
|
157
|
+
### 時間與時區
|
|
158
|
+
- **內部以 UTC 儲存與運算**;輸出呈現再格式化
|
|
159
|
+
- JSON 時間使用 RFC3339(必要時 `time.RFC3339Nano`)
|
|
160
|
+
|
|
161
|
+
### 安全性
|
|
162
|
+
- 僅用標準 `crypto/*`;禁自製密碼學
|
|
163
|
+
- 外部輸入需驗證與長度限制;避免正則 ReDoS
|
|
164
|
+
- 檔案 I/O 使用 `fs.FS` 與限制型讀取;防 Zip Slip
|
|
165
|
+
- 納入 `gosec`(或等價 analyzer)於 CI;敏感資訊不得進日誌
|
|
166
|
+
|
|
167
|
+
### 依賴與模組
|
|
168
|
+
- 模組遵循 **SemVer**;破壞性改動於 major path(`/v2`)
|
|
169
|
+
- 嚴格釘版:`go.mod` 使用最小相依原則;避免 transitive 泄漏
|
|
170
|
+
- 移除依賴需跑 `go mod tidy` 並附影響說明
|
|
171
|
+
|
|
172
|
+
### 設定檔與環境變數
|
|
173
|
+
- 使用 `spf13/viper` 管理設定
|
|
174
|
+
- **優先級**:環境變數 (ENV) > 設定檔 (yaml/json) > 預設值
|
|
175
|
+
- 結構定義範例:
|
|
176
|
+
```go
|
|
177
|
+
type Config struct {
|
|
178
|
+
Server ServerConfig `mapstructure:"server"`
|
|
179
|
+
Database DatabaseConfig `mapstructure:"database"`
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### 產生器與 Build
|
|
184
|
+
- 使用 `//go:build` 標籤管理條件編譯;禁止舊 `+build` 註解
|
|
185
|
+
- 建議使用 **Config/Env** 控制環境行為(12-Factor App 原則),避免 build tags 導致 binary 不一致
|
|
186
|
+
- `go generate` 指令須在檔頭註解,並可重複執行(可重入)
|
|
187
|
+
- CGO 預設關閉;開啟需 PR 說明平台/效能/部署影響
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 常用套件堆疊
|
|
192
|
+
|
|
193
|
+
### Web 框架
|
|
194
|
+
- `net/http` - 標準庫,適合簡單 API
|
|
195
|
+
- `github.com/gin-gonic/gin` - 高效能 Web 框架
|
|
196
|
+
|
|
197
|
+
### 資料庫
|
|
198
|
+
- `database/sql` - 標準 SQL 介面
|
|
199
|
+
- `github.com/jmoiron/sqlx` - SQL 擴充
|
|
200
|
+
- `gorm.io/gorm` - ORM 框架
|
|
201
|
+
|
|
202
|
+
### 工具類
|
|
203
|
+
- `github.com/spf13/cobra` - CLI 框架
|
|
204
|
+
- `github.com/spf13/viper` - 設定管理
|
|
205
|
+
- `github.com/vincent119/zlogger` - 高效能日誌
|
|
206
|
+
- `github.com/go-playground/validator` - Struct 驗證
|
|
207
|
+
- `go.uber.org/fx` - 依賴注入 (DI)
|
|
208
|
+
- `github.com/prometheus/client_golang` - Prometheus Metrics
|
|
209
|
+
- `github.com/redis/go-redis/v9` - Redis Client
|
|
210
|
+
- `github.com/vincent119/commons` - 常用工具庫
|
|
211
|
+
- `github.com/swaggo/swag` - Swagger 文件產生
|
|
212
|
+
- `uber-go/mock` - Mock 生成工具 (gomock)
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Review Checklist(精簡版)
|
|
217
|
+
|
|
218
|
+
- [ ] 僅一個 `package` 宣告(置頂)
|
|
219
|
+
- [ ] 通過 `gofmt -s` / `goimports` / `go vet`
|
|
220
|
+
- [ ] 無未使用 imports、無循環依賴
|
|
221
|
+
- [ ] `err` 立即檢查並以 `%w` 包裝;跨層以 `errors.Is/As`
|
|
222
|
+
- [ ] Goroutine / channel 正確收斂;無泄漏
|
|
223
|
+
- [ ] I/O 操作安全(含 Close、Pipe、Body 重新可讀)
|
|
224
|
+
- [ ] JSON tag 一致、解碼拒絕未知欄位、零值可用
|
|
225
|
+
- [ ] 測試含 table-driven、-race
|
|
226
|
+
- [ ] `go.mod` 依賴釘版;`go mod tidy` 後無不明變更
|
|
227
|
+
- [ ] 與 Uber / Effective Go 一致或於 PR 註明偏離理由
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Copilot / Agent 提示模板(Do/Don't)
|
|
232
|
+
|
|
233
|
+
**Do**
|
|
234
|
+
- 僅產生一個 `package` 宣告;imports 分群
|
|
235
|
+
- 立即檢查 `err`,使用 `%w` 包裝
|
|
236
|
+
- 所有公開 API 第一參數 `context.Context`
|
|
237
|
+
- 在邊界複製 slice/map;為 struct 加 `json`/`yaml` tags
|
|
238
|
+
- 撰寫 table-driven 測試 + `t.Helper()`
|
|
239
|
+
|
|
240
|
+
**Don't**
|
|
241
|
+
- 不要保存 `context.Context` 或 `*http.Request` 於 struct
|
|
242
|
+
- 不要在 library 使用 `panic`;不要忽略 `Close()`
|
|
243
|
+
- 不要以 `interface{}` 取代具體型別;不要暴露可變 slice/map
|
|
244
|
+
- 不要在長迴圈內直接 `defer` 造成延後釋放與資源累積;必要時以匿名函式縮小 scope,或顯式 `Close()`
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
> **進階主題已拆分為獨立 Skills**
|
|
249
|
+
> DDD 架構 | gRPC 規範 | 進階測試 | Database Migration | 可觀測性 | 優雅關機 | HTTP 進階 | API 設計 | 依賴注入 | 設定管理 | CI 工具 | Domain Events | 實作範例
|
|
250
|
+
>
|
|
251
|
+
> 使用時 Copilot 會根據對話內容自動載入相關 Skill。
|