Files
golang/golang-learning/10-projects/02-todo-list/todo/storage.go
2025-08-24 13:01:09 +08:00

309 lines
6.8 KiB
Go
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.

/*
storage.go - 数据存储
实现了任务数据的持久化存储
*/
package todo
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
)
// Storage 存储接口
type Storage interface {
Load() ([]Task, error)
Save(tasks []Task) error
}
// JSONStorage JSON文件存储实现
type JSONStorage struct {
filePath string
}
// NewJSONStorage 创建新的JSON存储
func NewJSONStorage(filePath string) (*JSONStorage, error) {
if filePath == "" {
return nil, fmt.Errorf("文件路径不能为空")
}
// 确保目录存在
dir := filepath.Dir(filePath)
if err := os.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("创建目录失败: %v", err)
}
return &JSONStorage{
filePath: filePath,
}, nil
}
// Load 从JSON文件加载任务
func (s *JSONStorage) Load() ([]Task, error) {
// 检查文件是否存在
if _, err := os.Stat(s.filePath); os.IsNotExist(err) {
// 文件不存在,返回空任务列表
return []Task{}, nil
}
// 读取文件内容
data, err := ioutil.ReadFile(s.filePath)
if err != nil {
return nil, fmt.Errorf("读取文件失败: %v", err)
}
// 如果文件为空,返回空任务列表
if len(data) == 0 {
return []Task{}, nil
}
// 解析JSON数据
var tasks []Task
if err := json.Unmarshal(data, &tasks); err != nil {
return nil, fmt.Errorf("解析JSON数据失败: %v", err)
}
return tasks, nil
}
// Save 保存任务到JSON文件
func (s *JSONStorage) Save(tasks []Task) error {
// 序列化任务数据
data, err := json.MarshalIndent(tasks, "", " ")
if err != nil {
return fmt.Errorf("序列化任务数据失败: %v", err)
}
// 写入文件
if err := ioutil.WriteFile(s.filePath, data, 0644); err != nil {
return fmt.Errorf("写入文件失败: %v", err)
}
return nil
}
// GetFilePath 获取文件路径
func (s *JSONStorage) GetFilePath() string {
return s.filePath
}
// FileExists 检查文件是否存在
func (s *JSONStorage) FileExists() bool {
_, err := os.Stat(s.filePath)
return !os.IsNotExist(err)
}
// GetFileSize 获取文件大小
func (s *JSONStorage) GetFileSize() (int64, error) {
info, err := os.Stat(s.filePath)
if err != nil {
return 0, err
}
return info.Size(), nil
}
// Backup 备份数据文件
func (s *JSONStorage) Backup(backupPath string) error {
if !s.FileExists() {
return fmt.Errorf("源文件不存在")
}
// 读取源文件
data, err := ioutil.ReadFile(s.filePath)
if err != nil {
return fmt.Errorf("读取源文件失败: %v", err)
}
// 确保备份目录存在
dir := filepath.Dir(backupPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("创建备份目录失败: %v", err)
}
// 写入备份文件
if err := ioutil.WriteFile(backupPath, data, 0644); err != nil {
return fmt.Errorf("写入备份文件失败: %v", err)
}
return nil
}
// Restore 从备份恢复数据
func (s *JSONStorage) Restore(backupPath string) error {
// 检查备份文件是否存在
if _, err := os.Stat(backupPath); os.IsNotExist(err) {
return fmt.Errorf("备份文件不存在")
}
// 读取备份文件
data, err := ioutil.ReadFile(backupPath)
if err != nil {
return fmt.Errorf("读取备份文件失败: %v", err)
}
// 验证备份数据
var tasks []Task
if err := json.Unmarshal(data, &tasks); err != nil {
return fmt.Errorf("备份数据格式无效: %v", err)
}
// 写入主文件
if err := ioutil.WriteFile(s.filePath, data, 0644); err != nil {
return fmt.Errorf("恢复数据失败: %v", err)
}
return nil
}
// Clear 清空数据文件
func (s *JSONStorage) Clear() error {
return s.Save([]Task{})
}
// MemoryStorage 内存存储实现(用于测试)
type MemoryStorage struct {
tasks []Task
}
// NewMemoryStorage 创建新的内存存储
func NewMemoryStorage() *MemoryStorage {
return &MemoryStorage{
tasks: make([]Task, 0),
}
}
// Load 从内存加载任务
func (s *MemoryStorage) Load() ([]Task, error) {
// 返回任务副本
tasks := make([]Task, len(s.tasks))
copy(tasks, s.tasks)
return tasks, nil
}
// Save 保存任务到内存
func (s *MemoryStorage) Save(tasks []Task) error {
// 保存任务副本
s.tasks = make([]Task, len(tasks))
copy(s.tasks, tasks)
return nil
}
// Clear 清空内存中的任务
func (s *MemoryStorage) Clear() {
s.tasks = make([]Task, 0)
}
// GetTasks 获取内存中的任务(用于测试)
func (s *MemoryStorage) GetTasks() []Task {
tasks := make([]Task, len(s.tasks))
copy(tasks, s.tasks)
return tasks
}
// CSVStorage CSV文件存储实现扩展功能
type CSVStorage struct {
filePath string
}
// NewCSVStorage 创建新的CSV存储
func NewCSVStorage(filePath string) (*CSVStorage, error) {
if filePath == "" {
return nil, fmt.Errorf("文件路径不能为空")
}
// 确保目录存在
dir := filepath.Dir(filePath)
if err := os.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("创建目录失败: %v", err)
}
return &CSVStorage{
filePath: filePath,
}, nil
}
// Load 从CSV文件加载任务简化实现
func (s *CSVStorage) Load() ([]Task, error) {
// 这里可以实现CSV解析逻辑
// 为了简化,暂时返回空列表
return []Task{}, nil
}
// Save 保存任务到CSV文件简化实现
func (s *CSVStorage) Save(tasks []Task) error {
// 这里可以实现CSV写入逻辑
// 为了简化,暂时不做任何操作
return nil
}
// StorageManager 存储管理器
type StorageManager struct {
storages map[string]Storage
current string
}
// NewStorageManager 创建新的存储管理器
func NewStorageManager() *StorageManager {
return &StorageManager{
storages: make(map[string]Storage),
}
}
// AddStorage 添加存储实现
func (sm *StorageManager) AddStorage(name string, storage Storage) {
sm.storages[name] = storage
}
// SetCurrent 设置当前使用的存储
func (sm *StorageManager) SetCurrent(name string) error {
if _, exists := sm.storages[name]; !exists {
return fmt.Errorf("存储 '%s' 不存在", name)
}
sm.current = name
return nil
}
// GetCurrent 获取当前存储
func (sm *StorageManager) GetCurrent() (Storage, error) {
if sm.current == "" {
return nil, fmt.Errorf("未设置当前存储")
}
storage, exists := sm.storages[sm.current]
if !exists {
return nil, fmt.Errorf("当前存储 '%s' 不存在", sm.current)
}
return storage, nil
}
// ListStorages 列出所有可用的存储
func (sm *StorageManager) ListStorages() []string {
var names []string
for name := range sm.storages {
names = append(names, name)
}
return names
}
// Load 使用当前存储加载数据
func (sm *StorageManager) Load() ([]Task, error) {
storage, err := sm.GetCurrent()
if err != nil {
return nil, err
}
return storage.Load()
}
// Save 使用当前存储保存数据
func (sm *StorageManager) Save(tasks []Task) error {
storage, err := sm.GetCurrent()
if err != nil {
return err
}
return storage.Save(tasks)
}