package file import ( "fmt" "os" "path/filepath" "sync" "gopkg.in/yaml.v2" ) // manager 是文件管理器的内部实现结构体,用于管理临时文件根路径和提供并发安全。 type manager struct { tempRoot string // 临时文件存储的根路径 mu sync.Mutex // 用于保证文件操作的线程安全 } var ( instance *manager once sync.Once ) // init 在包被导入时自动执行,用于初始化文件管理器单例。 func init() { once.Do(func() { instance = &manager{ tempRoot: "./tmp", // 默认的临时文件存储根路径 } }) } // SetTempRoot 设置临时文件存储的根目录。 // 此函数是线程安全的。 func SetTempRoot(path string) { instance.mu.Lock() defer instance.mu.Unlock() instance.tempRoot = path } // ExecuteWithLock 提供一个通用的、带回滚能力的事务性执行单元。 // 它会获取一个全局锁,然后执行 action。如果 action 执行出错,它将调用 onRollback。 // // action: 需要以原子方式执行的操作。 // onRollback: 当 action 返回错误时执行的回滚操作,原始错误会传入其中。 func ExecuteWithLock(action func() error, onRollback func(err error)) error { instance.mu.Lock() defer instance.mu.Unlock() err := action() if err != nil && onRollback != nil { onRollback(err) } return err } // CreateTempDir 在指定的根目录下创建一个子目录。 // 注意:此函数本身不是线程安全的,应在 ExecuteWithLock 的回调中使用。 func CreateTempDir(tempRoot, subDir string) (string, error) { fullDirPath := filepath.Join(tempRoot, subDir) if err := os.MkdirAll(fullDirPath, 0755); err != nil { return "", fmt.Errorf("创建临时目录 %s 失败: %w", fullDirPath, err) } return fullDirPath, nil } // PrepareTempFilePath 获取文件在指定子目录下的完整路径,并确保父目录存在。 // 注意:此函数本身不是线程安全的,应在 ExecuteWithLock 的回调中使用。 func PrepareTempFilePath(tempRoot, subDir, fileName string) (string, error) { fullDirPath := filepath.Join(tempRoot, subDir) if err := os.MkdirAll(fullDirPath, 0755); err != nil { return "", fmt.Errorf("创建临时文件父目录 %s 失败: %w", fullDirPath, err) } return filepath.Join(fullDirPath, fileName), nil } // RemoveTempDir 在指定的根目录下清理并删除一个子目录。 // 注意:此函数本身不是线程安全的,应在 ExecuteWithLock 的回调中使用。 func RemoveTempDir(tempRoot, subDir string) error { fullDirPath := filepath.Join(tempRoot, subDir) return os.RemoveAll(fullDirPath) } // RemoveDir 清理并删除指定的任意目录。 // 此函数与临时文件管理器无关,本身是线程安全的(依赖于操作系统的原子性)。 func RemoveDir(dirPath string) error { return os.RemoveAll(dirPath) } // LoadYaml 从指定路径加载并解析一个 YAML 文件到传入的结构体中。 // path: YAML 文件的路径。 // c: 目标结构体的指针,例如 &MyConfig{}。 func LoadYaml(path string, c interface{}) error { // 读取配置文件 data, err := os.ReadFile(path) if err != nil { return fmt.Errorf("配置文件读取失败: %w", err) } // 解析YAML配置 if err := yaml.Unmarshal(data, c); err != nil { return fmt.Errorf("配置文件解析失败: %w", err) } return nil } // WriteTempFile 将数据写入到临时子目录的指定文件中。 // 它会自动创建所需的子目录。 // 注意:此函数本身不是线程安全的,应在 ExecuteWithLock 的回调中使用。 func WriteTempFile(tempRoot, subDir, fileName string, data []byte) (string, error) { fullDirPath := filepath.Join(tempRoot, subDir) if err := os.MkdirAll(fullDirPath, 0755); err != nil { return "", fmt.Errorf("为写入操作创建临时目录 %s 失败: %w", fullDirPath, err) } filePath := filepath.Join(fullDirPath, fileName) if err := os.WriteFile(filePath, data, 0644); err != nil { return "", fmt.Errorf("写入临时文件 %s 失败: %w", filePath, err) } return filePath, nil } // ReadTempFile 从临时子目录的指定文件中读取数据。 // 注意:此函数本身不是线程安全的,应在 ExecuteWithLock 的回调中使用。 func ReadTempFile(tempRoot, subDir, fileName string) ([]byte, error) { filePath := filepath.Join(tempRoot, subDir, fileName) data, err := os.ReadFile(filePath) if err != nil { return nil, fmt.Errorf("读取临时文件 %s 失败: %w", filePath, err) } return data, nil }