# 文件管理模块代码风格规范

## 概述

本文档定义了文件管理模块的代码风格规范，确保代码一致性、可读性和可维护性。

---

## 1. 注释规范

### 1.1 包注释
每个包应该有一个简短的包注释，说明包的用途。

```go
// Package filesystem 提供文件系统操作功能
//
// 核心功能：
// - 文件读写、删除、列表
// - 路径验证和安全检查
// - ZIP文件操作
// - 审计日志和回收站
package filesystem
```

### 1.2 函数注释
使用标准Go文档注释风格：

```go
// DeletePath 删除文件或目录
//
// 参数:
//   path - 文件或目录路径
//
// 返回:
//   error - 错误信息，nil表示成功
//
// 示例:
//   err := fs.DeletePath("/path/to/file")
func (s *FileSystemService) DeletePath(path string) error {
    // 实现...
}
```

### 1.3 禁止的注释风格
```go
// 禁止使用emoji
// 🔒 安全检查
// ✅ 优化
// ⚠️ 警告

// 应使用纯文本
// 安全检查
// 性能优化
// 警告
```

---

## 2. 错误处理规范

### 2.1 错误包装
使用 WrapError 添加上下文：

```go
// 推荐做法
data, err := os.ReadFile(path)
if err != nil {
    return "", WrapError("读取文件", path, err)
}

// 避免裸错误
return "", err // ❌ 不推荐
return "", fmt.Errorf("失败: %w", err) // ✅ 推荐
```

### 2.2 错误消息
使用中文描述（面向中文用户）：

```go
// 推荐
return fmt.Errorf("文件不存在: %s", path)

// 避免使用英文
return fmt.Errorf("file not found: %s", path) // ❌
```

### 2.3 错误忽略
必须注释说明原因：

```go
// 推荐：注释说明原因
if err := logger.Close(); err != nil {
    // 日志关闭失败，程序即将退出，忽略错误
}

// 禁止：无注释忽略
_ = logger.Close() // ❌
```

---

## 3. 命名规范

### 3.1 常量命名
使用大驼峰命名法：

```go
const (
    MaxZipSize        = 100 * 1024 * 1024
    DefaultDirPermissions = 0755
    AuditFlushInterval  = 5 * time.Second
)
```

### 3.2 变量命名
使用小驼峰命名法：

```go
var (
    globalService     *FileSystemService
    defaultConfig      *Config
    defaultPermissions os.FileMode = 0644
)
```

### 3.3 接口命名
接口名应该是动作或能力的描述，通常以 -er 结尾：

```go
type Reader interface {
    Read(p []byte) (n int, err error)
}

type Validator interface {
    Validate(path string) error
}
```

---

## 4. 函数设计规范

### 4.1 函数长度
推荐单个函数不超过50行。如果超过，考虑拆分子函数：

```go
// 推荐：拆分子函数
func DeletePath(path string) error {
    if err := validatePath(path); err != nil {
        return err
    }

    if err := checkPermissions(path); err != nil {
        return err
    }

    return performDelete(path)
}

// 避免：长函数
func DeletePath(path string) error {
    // 100行代码...
}
```

### 4.2 参数数量
函数参数不超过5个。如果超过，使用结构体：

```go
// 推荐：使用结构体
type DeleteOptions struct {
    Path          string
    Force         bool
    SkipRecycle   bool
    IgnoreLock    bool
    Reason        string
}

func DeleteWithOptions(opts DeleteOptions) error {
    // 实现...
}

// 避免：过多参数
func DeleteWithOptions(path string, force bool, skipRecycle bool, ignoreLock bool, reason string, timeout int) error {
    // 参数过多
}
```

### 4.3 返回值
函数返回值遵循以下顺序：
1. 结果
2. 错误

```go
// 推荐
func ReadFile(path string) ([]byte, error)

// 避免多个返回值
func ReadFile(path string) ([]byte, bool, error, int)
```

---

## 5. 代码组织

### 5.1 文件组织
每个文件应该有单一的职责：

```
filesystem/
├── fs.go              # 核心文件操作
├── service.go         # 文件系统服务
├── path_validator.go  # 路径验证
├── filetype_manager.go # 文件类型管理
├── zip.go             # ZIP操作
├── errors.go          # 错误定义
├── logger.go          # 日志记录
└── constants.go       # 常量定义
```

### 5.2 导入顺序
标准库 → 第三方库 → 项目内部：

```go
import (
    // 标准库
    "context"
    "fmt"
    "os"

    // 第三方库
    "github.com/google/uuid"

    // 项目内部
    "go-desk/internal/common"
)
```

---

## 6. 性能规范

### 6.1 避免重复计算
使用缓存或预计算：

```go
// 推荐：缓存结果
type statsCache struct {
    mu    sync.RWMutex
    cache map[string]*DirectoryStats
}

func (c *statsCache) Get(path string) (*DirectoryStats, error) {
    c.mu.RLock()
    if stats, ok := c.cache[path]; ok {
        c.mu.RUnlock()
        return stats, nil
    }
    c.mu.RUnlock()

    // 计算并缓存
    stats, err := GetDirectoryStats(path)
    if err != nil {
        return nil, err
    }

    c.mu.Lock()
    c.cache[path] = stats
    c.mu.Unlock()

    return stats, nil
}

// 避免：重复计算
func processData(path string) {
    stats1, _ := GetDirectoryStats(path)
    stats2, _ := GetDirectoryStats(path) // 重复计算
}
```

### 6.2 资源释放
使用 defer 确保资源释放：

```go
// 推荐
func ReadFile(path string) ([]byte, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close() // 确保关闭

    return io.ReadAll(file)
}
```

---

## 7. 并发安全

### 7.1 共享状态
使用互斥锁保护共享状态：

```go
type SafeCounter struct {
    mu    sync.RWMutex
    count int
}

func (c *SafeCounter) Increment() {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.count++
}

func (c *SafeCounter) Get() int {
    c.mu.RLock()
    defer c.mu.RUnlock()
    return c.count
}
```

### 7.2 避免数据竞争
不要在goroutine中直接共享变量：

```go
// 推荐：传递参数
for i := 0; i < 10; i++ {
    go func(n int) {
        fmt.Println(n)
    }(i)
}

// 避免：闭包捕获
for i := 0; i < 10; i++ {
    go func() {
        fmt.Println(i) // 数据竞争
    }()
}
```

---

## 8. 测试规范

### 8.1 测试文件命名
测试文件命名为 `xxx_test.go`：

```go
// fs_test.go
package filesystem

import "testing"

func TestDeletePath(t *testing.T) {
    // 测试代码
}
```

### 8.2 表格驱动测试
使用表格驱动测试多种场景：

```go
func TestValidatePath(t *testing.T) {
    tests := []struct {
        name    string
        path    string
        wantErr bool
    }{
        {"正常路径", "/tmp/test.txt", false},
        {"路径遍历", "/tmp/../etc/passwd", true},
        {"空路径", "", true},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            err := ValidatePath(tt.path)
            if (err != nil) != tt.wantErr {
                t.Errorf("ValidatePath() error = %v, wantErr %v", err, tt.wantErr)
            }
        })
    }
}
```

---

## 9. 文档规范

### 9.1 README
每个模块应该有README说明：

```markdown
# 文件系统模块

## 功能
- 文件读写
- 路径验证
- ZIP操作

## 使用示例
...

## 配置
...
```

### 9.2 API文档
导出的函数和类型必须有文档注释。

---

## 10. 代码审查清单

提交代码前，确保：

- [ ] 移除所有emoji注释
- [ ] 函数有文档注释
- [ ] 错误处理完善（无忽略错误）
- [ ] 命名符合规范
- [ ] 无魔法数字（使用常量）
- [ ] 无重复代码（遵循DRY）
- [ ] 导入顺序正确
- [ ] 资源正确释放（defer）

---

*版本: 1.0*
*最后更新: 2026-01-27*
