zco-claude 0.0.8__py3-none-any.whl

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.
Files changed (34) hide show
  1. ClaudeSettings/DOT.claudeignore +7 -0
  2. ClaudeSettings/README.md +100 -0
  3. ClaudeSettings/commands/generate_changelog.sh +49 -0
  4. ClaudeSettings/commands/show_env +92 -0
  5. ClaudeSettings/commands/zco-clean +164 -0
  6. ClaudeSettings/commands/zco-git-summary +15 -0
  7. ClaudeSettings/commands/zco-git-tag +42 -0
  8. ClaudeSettings/hooks/CHANGELOG.md +157 -0
  9. ClaudeSettings/hooks/README.md +254 -0
  10. ClaudeSettings/hooks/save_chat_plain.py +148 -0
  11. ClaudeSettings/hooks/save_chat_spec.py +398 -0
  12. ClaudeSettings/rules/README.md +270 -0
  13. ClaudeSettings/rules/go/.golangci.yml.template +170 -0
  14. ClaudeSettings/rules/go/GoBuildAutoVersion.v250425.md +95 -0
  15. ClaudeSettings/rules/go/check-standards.sh +128 -0
  16. ClaudeSettings/rules/go/coding-standards.md +973 -0
  17. ClaudeSettings/rules/go/example.go +207 -0
  18. ClaudeSettings/rules/go/go-testing.md +691 -0
  19. ClaudeSettings/rules/go/list-comments.sh +85 -0
  20. ClaudeSettings/settings.sample.json +71 -0
  21. ClaudeSettings/skills/README.md +225 -0
  22. ClaudeSettings/skills/zco-docs-update/SKILL.md +381 -0
  23. ClaudeSettings/skills/zco-help/SKILL.md +601 -0
  24. ClaudeSettings/skills/zco-plan/SKILL.md +661 -0
  25. ClaudeSettings/skills/zco-plan-new/SKILL.md +585 -0
  26. ClaudeSettings/zco-scripts/co-docs-update.sh +150 -0
  27. ClaudeSettings/zco-scripts/test_update_plan_metadata.py +328 -0
  28. ClaudeSettings/zco-scripts/update-plan-metadata.py +324 -0
  29. zco_claude-0.0.8.dist-info/METADATA +190 -0
  30. zco_claude-0.0.8.dist-info/RECORD +34 -0
  31. zco_claude-0.0.8.dist-info/WHEEL +5 -0
  32. zco_claude-0.0.8.dist-info/entry_points.txt +3 -0
  33. zco_claude-0.0.8.dist-info/top_level.txt +1 -0
  34. zco_claude_init.py +1732 -0
@@ -0,0 +1,973 @@
1
+ # Go 项目编程标准
2
+
3
+ ## 注释规范
4
+
5
+ ### 注释类型区分(核心约定)
6
+
7
+ 本项目使用不同的注释标记来区分注释的用途:
8
+
9
+ #### 1. 代码功能注释 `//; `
10
+ **用途**:解释代码的功能、逻辑、算法, 跟纯代码注释"//"区分
11
+
12
+ **使用场景**:
13
+ - 解释复杂的业务逻辑
14
+ - 说明算法实现思路
15
+ - 阐述为什么这样写(设计决策)
16
+ - 公共 API 的文档注释
17
+
18
+ **示例**:
19
+ ```go
20
+ //; CalculateDiscount 根据订单金额和用户等级计算折扣
21
+ //; 折扣规则:
22
+ //; - VIP 用户:订单金额的 15%
23
+ //; - 普通用户:订单金额的 10%
24
+ //; - 订单金额 < 100 元不享受折扣
25
+ func CalculateDiscount(amount float64, userLevel string) float64 {
26
+ //; 小额订单不参与折扣活动
27
+ if amount < 100 {
28
+ return 0
29
+ }
30
+
31
+ //; 根据用户等级计算折扣率
32
+ var rate float64
33
+ switch userLevel {
34
+ case "VIP":
35
+ rate = 0.15
36
+ default:
37
+ rate = 0.10
38
+ }
39
+
40
+ return amount * rate
41
+ }
42
+ ```
43
+
44
+ #### 2. 非代码注释 `//;@`
45
+ **用途**:元信息、开发备注、待办事项、调试信息
46
+
47
+ **使用场景**:
48
+ - `//;@TODO:` - 待实现的功能
49
+ - `//;@FIXME:` - 需要修复的问题
50
+ - `//;@NOTE:` - 开发者备注
51
+ - `//;@HACK:` - 临时解决方案
52
+ - `//;@OPTIMIZE:` - 性能优化点
53
+ - `//;@DEPRECATED:` - 已废弃的代码
54
+ - `//;@DEBUG:` - 调试信息
55
+ - `//;@XXX:` - 需要注意的问题
56
+
57
+ **示例**:
58
+ ```go
59
+ func ProcessOrder(order *Order) error {
60
+ //;@TODO: 添加订单金额验证
61
+ //;@NOTE: 这里需要考虑并发安全问题
62
+
63
+ // 计算订单总金额
64
+ total := calculateTotal(order)
65
+
66
+ //;@FIXME: Redis 连接偶尔会超时,需要添加重试机制
67
+ if err := cache.Set(order.ID, total); err != nil {
68
+ return err
69
+ }
70
+
71
+ //;@HACK: 临时方案,等待支付网关 API 升级后移除
72
+ if order.PaymentMethod == "alipay_v1" {
73
+ return processLegacyAlipay(order)
74
+ }
75
+
76
+ //;@OPTIMIZE: 这里可以使用批量查询减少数据库访问
77
+ for _, item := range order.Items {
78
+ product, err := db.GetProduct(item.ProductID)
79
+ if err != nil {
80
+ return err
81
+ }
82
+ //; 处理商品...
83
+ }
84
+
85
+ return nil
86
+ }
87
+
88
+ //;@DEPRECATED: 使用 ProcessOrderV2 替代
89
+ //;此函数将在 v2.0 版本移除
90
+ func ProcessOrderLegacy(order *Order) error {
91
+ // ...
92
+ }
93
+ ```
94
+
95
+ #### 3. 注释使用原则
96
+
97
+ **强制规则(MUST)**:
98
+ - ✅ 所有导出的函数、类型、常量必须有文档注释(使用 `//`)
99
+ - ✅ 复杂逻辑必须有解释注释(使用 `//`)
100
+ - ✅ 所有 TODO、FIXME 等必须使用 `//;` 前缀
101
+ - ✅ 调试注释、临时备注必须使用 `//;` 前缀
102
+ - ❌ 禁止用注释注释掉代码(应该删除或使用 Git)
103
+
104
+ **推荐规则(SHOULD)**:
105
+ - 注释应该解释"为什么"而不是"是什么"
106
+ - 代码应该自解释,减少不必要的注释
107
+ - 注释应该与代码保持同步更新
108
+
109
+ **注释检查工具**:
110
+ ```bash
111
+ # 查找所有非代码注释
112
+ grep -r "//;" . --include="*.go"
113
+
114
+ # 查找所有 TODO
115
+ grep -r "//;@TODO:" . --include="*.go"
116
+
117
+ # 查找所有需要修复的问题
118
+ grep -r "//;@FIXME:" . --include="*.go"
119
+
120
+ # 查找已废弃的代码
121
+ grep -r "//;@DEPRECATED:" . --include="*.go"
122
+ ```
123
+
124
+ ---
125
+
126
+ ## 命名规范
127
+
128
+ ### 包命名
129
+
130
+ **规则**:
131
+ - 使用小写单词,不使用下划线或驼峰
132
+ - 简短且有意义
133
+ - 避免使用泛化名称(util、common、base)
134
+
135
+ **示例**:
136
+ ```go
137
+ ✅ package user
138
+ ✅ package payment
139
+ ✅ package cache
140
+
141
+ ❌ package userService
142
+ ❌ package user_service
143
+ ❌ package utils
144
+ ```
145
+
146
+ ### 变量命名
147
+
148
+ **规则**:
149
+ - 使用驼峰命名法(camelCase)
150
+ - 导出变量使用大写开头(PascalCase)
151
+ - 缩写词保持一致的大小写(ID、URL、HTTP)
152
+ - 单字母变量仅用于短循环
153
+
154
+ **示例**:
155
+ ```go
156
+ // 普通变量
157
+ var userName string
158
+ var orderCount int
159
+
160
+ // 导出变量
161
+ var MaxRetryCount = 3
162
+ var DefaultTimeout = 30 * time.Second
163
+
164
+ // 缩写词
165
+ var userID int64 // ✅
166
+ var userUrl string // ❌ 应该是 userURL
167
+ var HTTPClient *http.Client // ✅
168
+
169
+ // 循环变量
170
+ for i := 0; i < len(items); i++ { // ✅ 短循环可以用 i
171
+ // ...
172
+ }
173
+
174
+ for index, item := range items { // ✅ 长循环用有意义的名字
175
+ // ...
176
+ }
177
+ ```
178
+
179
+ ### 函数命名
180
+
181
+ **规则**:
182
+ - 使用驼峰命名法
183
+ - 动词开头,表达清晰的动作
184
+ - 布尔返回值的函数以 `is`、`has`、`can` 等开头
185
+
186
+ **示例**:
187
+ ```go
188
+ // 普通函数
189
+ func calculateTotal(items []Item) float64 { }
190
+ func sendEmail(to string, body string) error { }
191
+
192
+ // 导出函数
193
+ func CreateUser(name, email string) (*User, error) { }
194
+ func UpdateOrder(id int64, status string) error { }
195
+
196
+ // 布尔函数
197
+ func isValid(email string) bool { }
198
+ func hasPermission(user *User, resource string) bool { }
199
+ func canEdit(user *User) bool { }
200
+
201
+ // Getter/Setter
202
+ func (u *User) Name() string { return u.name } // ✅
203
+ func (u *User) SetName(name string) { u.name = name } // ✅
204
+ func (u *User) GetName() string { } // ❌ Go 不用 Get 前缀
205
+ ```
206
+
207
+ ### 常量命名
208
+
209
+ **规则**:
210
+ - 导出常量使用大写开头驼峰
211
+ - 私有常量使用小写开头驼峰
212
+ - 枚举值使用类型名作为前缀
213
+
214
+ **示例**:
215
+ ```go
216
+ // 导出常量
217
+ const (
218
+ MaxLoginAttempts = 5
219
+ DefaultPageSize = 20
220
+ APIVersion = "v1"
221
+ )
222
+
223
+ // 私有常量
224
+ const (
225
+ maxRetries = 3
226
+ defaultTimeout = 30
227
+ )
228
+
229
+ // 枚举(使用类型前缀)
230
+ type OrderStatus int
231
+
232
+ const (
233
+ OrderStatusPending OrderStatus = iota
234
+ OrderStatusPaid
235
+ OrderStatusShipped
236
+ OrderStatusCompleted
237
+ OrderStatusCancelled
238
+ )
239
+ ```
240
+
241
+ ### 接口命名
242
+
243
+ **规则**:
244
+ - 单方法接口使用 `-er` 后缀
245
+ - 多方法接口使用有意义的名词
246
+
247
+ **示例**:
248
+ ```go
249
+ // 单方法接口
250
+ type Reader interface {
251
+ Read(p []byte) (n int, err error)
252
+ }
253
+
254
+ type Writer interface {
255
+ Write(p []byte) (n int, err error)
256
+ }
257
+
258
+ type Closer interface {
259
+ Close() error
260
+ }
261
+
262
+ // 多方法接口
263
+ type UserRepository interface {
264
+ Create(user *User) error
265
+ FindByID(id int64) (*User, error)
266
+ Update(user *User) error
267
+ Delete(id int64) error
268
+ }
269
+ ```
270
+
271
+ ---
272
+
273
+ ## 代码组织
274
+
275
+ ### 文件结构
276
+
277
+ **标准文件顺序**:
278
+ ```go
279
+ // 1. Package 声明
280
+ package user
281
+
282
+ // 2. Import 分组(标准库 -> 第三方库 -> 本项目)
283
+ import (
284
+ // 标准库
285
+ "context"
286
+ "fmt"
287
+ "time"
288
+
289
+ // 第三方库
290
+ "github.com/gin-gonic/gin"
291
+ "gorm.io/gorm"
292
+
293
+ // 本项目
294
+ "yourproject/internal/model"
295
+ "yourproject/pkg/logger"
296
+ )
297
+
298
+ // 3. 常量定义
299
+ const (
300
+ MaxNameLength = 50
301
+ )
302
+
303
+ // 4. 变量定义
304
+ var (
305
+ DefaultTimeout = 30 * time.Second
306
+ )
307
+
308
+ // 5. 类型定义
309
+ type User struct {
310
+ ID int64
311
+ Name string
312
+ Email string
313
+ CreatedAt time.Time
314
+ }
315
+
316
+ // 6. 构造函数
317
+ func NewUser(name, email string) *User {
318
+ return &User{
319
+ Name: name,
320
+ Email: email,
321
+ CreatedAt: time.Now(),
322
+ }
323
+ }
324
+
325
+ // 7. 接口实现和方法
326
+ func (u *User) Validate() error {
327
+ // ...
328
+ }
329
+
330
+ // 8. 公共函数
331
+ func CreateUser(ctx context.Context, user *User) error {
332
+ // ...
333
+ }
334
+
335
+ // 9. 私有函数
336
+ func validateEmail(email string) bool {
337
+ // ...
338
+ }
339
+ ```
340
+
341
+ ### 包结构
342
+
343
+ **推荐的项目结构**:
344
+ ```
345
+ project/
346
+ ├── cmd/ # 主程序入口
347
+ │ └── server/
348
+ │ └── main.go
349
+ ├── internal/ # 私有代码
350
+ │ ├── handler/ # HTTP 处理器
351
+ │ ├── service/ # 业务逻辑
352
+ │ ├── repository/ # 数据访问
353
+ │ └── model/ # 数据模型
354
+ ├── pkg/ # 可导出的库
355
+ │ ├── logger/
356
+ │ └── cache/
357
+ ├── api/ # API 定义(protobuf、OpenAPI)
358
+ ├── config/ # 配置文件
359
+ ├── scripts/ # 脚本文件
360
+ └── test/ # 测试数据、集成测试
361
+ ```
362
+
363
+ **分层原则**:
364
+ ```go
365
+ // ✅ 推荐:清晰的分层
366
+ handler -> service -> repository -> database
367
+ | | |
368
+ v v v
369
+ HTTP 业务逻辑 数据访问
370
+
371
+ // ❌ 禁止:跨层调用
372
+ handler -> repository (跳过 service)
373
+ handler -> database (跳过 service 和 repository)
374
+ ```
375
+
376
+ ---
377
+
378
+ ## 错误处理
379
+
380
+ ### 错误定义
381
+
382
+ **规则**:
383
+ - 使用 `errors.New()` 定义简单错误
384
+ - 使用自定义错误类型处理复杂错误
385
+ - 错误信息使用小写,不以标点结尾
386
+ - 使用 `fmt.Errorf()` 包装错误并添加上下文
387
+
388
+ **示例**:
389
+ ```go
390
+ import (
391
+ "errors"
392
+ "fmt"
393
+ )
394
+
395
+ // 简单错误
396
+ var (
397
+ ErrUserNotFound = errors.New("user not found")
398
+ ErrInvalidEmail = errors.New("invalid email format")
399
+ ErrDuplicateEmail = errors.New("email already exists")
400
+ )
401
+
402
+ // 自定义错误类型
403
+ type ValidationError struct {
404
+ Field string
405
+ Message string
406
+ }
407
+
408
+ func (e *ValidationError) Error() string {
409
+ return fmt.Sprintf("validation failed on field '%s': %s", e.Field, e.Message)
410
+ }
411
+
412
+ // 错误包装
413
+ func GetUser(id int64) (*User, error) {
414
+ user, err := db.FindByID(id)
415
+ if err != nil {
416
+ //;@NOTE: 使用 %w 可以保留原始错误,支持 errors.Is() 和 errors.As()
417
+ return nil, fmt.Errorf("failed to get user %d: %w", id, err)
418
+ }
419
+ return user, nil
420
+ }
421
+
422
+ // 错误检查
423
+ func ProcessUser(id int64) error {
424
+ user, err := GetUser(id)
425
+ if err != nil {
426
+ // 使用 errors.Is 检查特定错误
427
+ if errors.Is(err, ErrUserNotFound) {
428
+ return fmt.Errorf("cannot process: user %d not found", id)
429
+ }
430
+ return err
431
+ }
432
+ // ...
433
+ return nil
434
+ }
435
+ ```
436
+
437
+ ### 错误处理模式
438
+
439
+ **推荐模式**:
440
+ ```go
441
+ // ✅ 推荐:及早返回
442
+ func ProcessOrder(order *Order) error {
443
+ if err := validateOrder(order); err != nil {
444
+ return fmt.Errorf("validation failed: %w", err)
445
+ }
446
+
447
+ if err := checkInventory(order); err != nil {
448
+ return fmt.Errorf("inventory check failed: %w", err)
449
+ }
450
+
451
+ if err := processPayment(order); err != nil {
452
+ return fmt.Errorf("payment processing failed: %w", err)
453
+ }
454
+
455
+ return nil
456
+ }
457
+
458
+ // ❌ 避免:嵌套过深
459
+ func ProcessOrder(order *Order) error {
460
+ if err := validateOrder(order); err == nil {
461
+ if err := checkInventory(order); err == nil {
462
+ if err := processPayment(order); err == nil {
463
+ return nil
464
+ } else {
465
+ return err
466
+ }
467
+ } else {
468
+ return err
469
+ }
470
+ } else {
471
+ return err
472
+ }
473
+ }
474
+ ```
475
+
476
+ ---
477
+
478
+ ## 函数设计
479
+
480
+ ### 函数长度
481
+
482
+ **规则**:
483
+ - 单个函数 ≤ 50 行(推荐)
484
+ - 圈复杂度 ≤ 10
485
+ - 参数数量 ≤ 5 个
486
+
487
+ **重构建议**:
488
+ ```go
489
+ // ❌ 函数过长
490
+ func ProcessOrder(order *Order) error {
491
+ // 100+ 行代码...
492
+ }
493
+
494
+ // ✅ 拆分为多个小函数
495
+ func ProcessOrder(order *Order) error {
496
+ if err := validateOrder(order); err != nil {
497
+ return err
498
+ }
499
+
500
+ if err := calculateTotal(order); err != nil {
501
+ return err
502
+ }
503
+
504
+ if err := processPayment(order); err != nil {
505
+ return err
506
+ }
507
+
508
+ if err := updateInventory(order); err != nil {
509
+ return err
510
+ }
511
+
512
+ return nil
513
+ }
514
+
515
+ func validateOrder(order *Order) error { /* ... */ }
516
+ func calculateTotal(order *Order) error { /* ... */ }
517
+ func processPayment(order *Order) error { /* ... */ }
518
+ func updateInventory(order *Order) error { /* ... */ }
519
+ ```
520
+
521
+ ### 参数传递
522
+
523
+ **规则**:
524
+ - 超过 3 个参数考虑使用配置结构体
525
+ - 使用选项模式(Functional Options Pattern)处理可选参数
526
+
527
+ **示例**:
528
+ ```go
529
+ // ❌ 参数过多
530
+ func CreateUser(name, email, phone, address, city, country string, age int, isActive bool) error {
531
+ // ...
532
+ }
533
+
534
+ // ✅ 使用结构体
535
+ type CreateUserRequest struct {
536
+ Name string
537
+ Email string
538
+ Phone string
539
+ Address string
540
+ City string
541
+ Country string
542
+ Age int
543
+ IsActive bool
544
+ }
545
+
546
+ func CreateUser(req *CreateUserRequest) error {
547
+ // ...
548
+ }
549
+
550
+ // ✅ 使用选项模式
551
+ type UserOption func(*User)
552
+
553
+ func WithPhone(phone string) UserOption {
554
+ return func(u *User) {
555
+ u.Phone = phone
556
+ }
557
+ }
558
+
559
+ func WithAddress(address string) UserOption {
560
+ return func(u *User) {
561
+ u.Address = address
562
+ }
563
+ }
564
+
565
+ func NewUser(name, email string, opts ...UserOption) *User {
566
+ user := &User{
567
+ Name: name,
568
+ Email: email,
569
+ }
570
+
571
+ for _, opt := range opts {
572
+ opt(user)
573
+ }
574
+
575
+ return user
576
+ }
577
+
578
+ // 使用
579
+ user := NewUser("John", "john@example.com",
580
+ WithPhone("123456"),
581
+ WithAddress("123 Main St"),
582
+ )
583
+ ```
584
+
585
+ ---
586
+
587
+ ## 并发编程
588
+
589
+ ### Goroutine 使用
590
+
591
+ **规则**:
592
+ - 明确 goroutine 的生命周期
593
+ - 避免 goroutine 泄漏
594
+ - 使用 context 控制 goroutine 退出
595
+
596
+ **示例**:
597
+ ```go
598
+ // ✅ 推荐:使用 context 控制
599
+ func StartWorker(ctx context.Context) {
600
+ go func() {
601
+ ticker := time.NewTicker(1 * time.Second)
602
+ defer ticker.Stop()
603
+
604
+ for {
605
+ select {
606
+ case <-ctx.Done():
607
+ //;@NOTE: Context 取消时退出
608
+ return
609
+ case <-ticker.C:
610
+ // 执行任务
611
+ doWork()
612
+ }
613
+ }
614
+ }()
615
+ }
616
+
617
+ // ❌ 避免:无法控制的 goroutine
618
+ func StartWorker() {
619
+ go func() {
620
+ for {
621
+ time.Sleep(1 * time.Second)
622
+ doWork() // 永远无法停止
623
+ }
624
+ }()
625
+ }
626
+ ```
627
+
628
+ ### Channel 使用
629
+
630
+ **规则**:
631
+ - 只有发送方关闭 channel
632
+ - 使用 buffered channel 避免阻塞
633
+ - 使用 select 处理多个 channel
634
+
635
+ **示例**:
636
+ ```go
637
+ // ✅ 推荐模式
638
+ func Producer(ctx context.Context) <-chan int {
639
+ ch := make(chan int, 10) // buffered channel
640
+
641
+ go func() {
642
+ defer close(ch) // 发送方关闭 channel
643
+
644
+ for i := 0; i < 100; i++ {
645
+ select {
646
+ case <-ctx.Done():
647
+ return
648
+ case ch <- i:
649
+ // 发送数据
650
+ }
651
+ }
652
+ }()
653
+
654
+ return ch
655
+ }
656
+
657
+ func Consumer(ctx context.Context, ch <-chan int) {
658
+ for {
659
+ select {
660
+ case <-ctx.Done():
661
+ return
662
+ case val, ok := <-ch:
663
+ if !ok {
664
+ //;@NOTE: Channel 已关闭
665
+ return
666
+ }
667
+ process(val)
668
+ }
669
+ }
670
+ }
671
+ ```
672
+
673
+ ### Mutex 使用
674
+
675
+ **规则**:
676
+ - 锁的粒度尽可能小
677
+ - 避免在持有锁时调用外部函数
678
+ - 使用 defer 确保解锁
679
+
680
+ **示例**:
681
+ ```go
682
+ type SafeCounter struct {
683
+ mu sync.Mutex
684
+ count int
685
+ }
686
+
687
+ // ✅ 推荐:使用 defer 解锁
688
+ func (c *SafeCounter) Inc() {
689
+ c.mu.Lock()
690
+ defer c.mu.Unlock()
691
+ c.count++
692
+ }
693
+
694
+ // ✅ 推荐:减小锁粒度
695
+ func (c *SafeCounter) GetAndReset() int {
696
+ c.mu.Lock()
697
+ count := c.count
698
+ c.count = 0
699
+ c.mu.Unlock()
700
+
701
+ // 在锁外执行耗时操作
702
+ log.Printf("counter was %d", count)
703
+
704
+ return count
705
+ }
706
+
707
+ // ❌ 避免:锁粒度过大
708
+ func (c *SafeCounter) GetAndReset() int {
709
+ c.mu.Lock()
710
+ defer c.mu.Unlock()
711
+
712
+ count := c.count
713
+ c.count = 0
714
+
715
+ // 在持有锁时执行耗时操作(阻塞其他 goroutine)
716
+ log.Printf("counter was %d", count)
717
+ time.Sleep(100 * time.Millisecond)
718
+
719
+ return count
720
+ }
721
+ ```
722
+
723
+ ---
724
+
725
+ ## 测试规范
726
+
727
+ ### 测试文件组织
728
+
729
+ **规则**:
730
+ - 测试文件以 `_test.go` 结尾
731
+ - 测试函数以 `Test` 开头
732
+ - 使用表驱动测试
733
+
734
+ **示例**:
735
+ ```go
736
+ // user.go
737
+ package user
738
+
739
+ func ValidateEmail(email string) bool {
740
+ // ...
741
+ }
742
+
743
+ // user_test.go
744
+ package user
745
+
746
+ import "testing"
747
+
748
+ func TestValidateEmail(t *testing.T) {
749
+ tests := []struct {
750
+ name string
751
+ email string
752
+ want bool
753
+ }{
754
+ {
755
+ name: "valid email",
756
+ email: "test@example.com",
757
+ want: true,
758
+ },
759
+ {
760
+ name: "missing @",
761
+ email: "testexample.com",
762
+ want: false,
763
+ },
764
+ {
765
+ name: "empty email",
766
+ email: "",
767
+ want: false,
768
+ },
769
+ }
770
+
771
+ for _, tt := range tests {
772
+ t.Run(tt.name, func(t *testing.T) {
773
+ got := ValidateEmail(tt.email)
774
+ if got != tt.want {
775
+ t.Errorf("ValidateEmail(%q) = %v, want %v",
776
+ tt.email, got, tt.want)
777
+ }
778
+ })
779
+ }
780
+ }
781
+ ```
782
+
783
+ ### 测试覆盖率
784
+
785
+ **要求**:
786
+ - 单元测试覆盖率 ≥ 80%
787
+ - 关键业务逻辑覆盖率 ≥ 95%
788
+
789
+ **检查命令**:
790
+ ```bash
791
+ # 运行测试并查看覆盖率
792
+ go test -cover ./...
793
+
794
+ # 生成覆盖率报告
795
+ go test -coverprofile=coverage.out ./...
796
+ go tool cover -html=coverage.out
797
+ ```
798
+
799
+ ---
800
+
801
+ ## 性能优化
802
+
803
+ ### 字符串拼接
804
+
805
+ **规则**:
806
+ - 少量拼接使用 `+`
807
+ - 循环中使用 `strings.Builder`
808
+ - 格式化使用 `fmt.Sprintf()`
809
+
810
+ **示例**:
811
+ ```go
812
+ // ✅ 少量拼接
813
+ name := firstName + " " + lastName
814
+
815
+ // ✅ 循环中拼接
816
+ func JoinStrings(items []string) string {
817
+ var builder strings.Builder
818
+ for _, item := range items {
819
+ builder.WriteString(item)
820
+ builder.WriteString(",")
821
+ }
822
+ return builder.String()
823
+ }
824
+
825
+ // ❌ 避免:循环中使用 +
826
+ func JoinStrings(items []string) string {
827
+ result := ""
828
+ for _, item := range items {
829
+ result += item + "," // 每次都会创建新字符串
830
+ }
831
+ return result
832
+ }
833
+ ```
834
+
835
+ ### Slice 使用
836
+
837
+ **规则**:
838
+ - 预分配容量避免多次扩容
839
+ - 注意 slice 共享底层数组的问题
840
+
841
+ **示例**:
842
+ ```go
843
+ // ✅ 预分配容量
844
+ func ProcessItems(n int) []Item {
845
+ items := make([]Item, 0, n) // 预分配容量
846
+ for i := 0; i < n; i++ {
847
+ items = append(items, createItem(i))
848
+ }
849
+ return items
850
+ }
851
+
852
+ // ❌ 未预分配容量
853
+ func ProcessItems(n int) []Item {
854
+ var items []Item // 会多次扩容
855
+ for i := 0; i < n; i++ {
856
+ items = append(items, createItem(i))
857
+ }
858
+ return items
859
+ }
860
+ ```
861
+
862
+ ---
863
+
864
+ ## 代码审查清单
865
+
866
+ ### 提交前检查
867
+
868
+ **必须检查项**:
869
+ - [ ] 代码已格式化(`go fmt`)
870
+ - [ ] 通过 linter 检查(`golangci-lint run`)
871
+ - [ ] 所有测试通过(`go test ./...`)
872
+ - [ ] 测试覆盖率达标(≥ 80%)
873
+ - [ ] 没有 race condition(`go test -race ./...`)
874
+ - [ ] 注释使用正确的标记(`//` vs `//;`)
875
+ - [ ] 所有 `//;@TODO` 和 `//;@FIXME` 都已记录
876
+
877
+ **推荐检查项**:
878
+ - [ ] 函数长度 ≤ 50 行
879
+ - [ ] 圈复杂度 ≤ 10
880
+ - [ ] 没有重复代码
881
+ - [ ] 错误处理完整
882
+ - [ ] 没有明显的性能问题
883
+
884
+ ---
885
+
886
+ ## 工具配置
887
+
888
+ ### golangci-lint 配置
889
+
890
+ 创建 `.golangci.yml`:
891
+ ```yaml
892
+ linters:
893
+ enable:
894
+ - gofmt
895
+ - goimports
896
+ - govet
897
+ - errcheck
898
+ - staticcheck
899
+ - unused
900
+ - gosimple
901
+ - ineffassign
902
+ - deadcode
903
+ - typecheck
904
+ - gocyclo
905
+ - funlen
906
+ - gocognit
907
+
908
+ linters-settings:
909
+ gocyclo:
910
+ min-complexity: 10
911
+ funlen:
912
+ lines: 50
913
+ statements: 40
914
+ errcheck:
915
+ check-blank: true
916
+ govet:
917
+ check-shadowing: true
918
+
919
+ issues:
920
+ exclude-rules:
921
+ - path: _test\.go
922
+ linters:
923
+ - funlen
924
+ - gocyclo
925
+ ```
926
+
927
+ ### VS Code 配置
928
+
929
+ 创建 `.vscode/settings.json`:
930
+ ```json
931
+ {
932
+ "go.lintTool": "golangci-lint",
933
+ "go.lintOnSave": "package",
934
+ "go.formatTool": "gofmt",
935
+ "editor.formatOnSave": true,
936
+ "go.testOnSave": false,
937
+ "go.coverOnSave": false
938
+ }
939
+ ```
940
+
941
+ ---
942
+
943
+ ## 总结
944
+
945
+ 本编程标准的核心要点:
946
+
947
+ 1. **注释区分**:
948
+ - `//` 用于代码功能注释
949
+ - `//;` 用于 TODO、FIXME、DEBUG 等元信息
950
+
951
+ 2. **代码质量**:
952
+ - 函数长度 ≤ 50 行
953
+ - 圈复杂度 ≤ 10
954
+ - 测试覆盖率 ≥ 80%
955
+
956
+ 3. **错误处理**:
957
+ - 使用 `fmt.Errorf()` 包装错误
958
+ - 及早返回,避免嵌套
959
+
960
+ 4. **并发安全**:
961
+ - 使用 context 控制生命周期
962
+ - 避免 goroutine 泄漏
963
+ - 正确使用 mutex
964
+
965
+ 5. **测试要求**:
966
+ - 使用表驱动测试
967
+ - 确保测试覆盖率
968
+ - 运行 race detector
969
+
970
+ **参考资源**:
971
+ - [Effective Go](https://golang.org/doc/effective_go)
972
+ - [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
973
+ - [Uber Go Style Guide](https://github.com/uber-go/guide)