Private
Public Access
1
0
Files
u-desk/docs/03-模块文档/文件系统/filesystem-code-style-guide.md

430 lines
7.4 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.
# 文件管理模块代码风格规范
## 概述
本文档定义了文件管理模块的代码风格规范,确保代码一致性、可读性和可维护性。
---
## 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*