完成
This commit is contained in:
308
golang-learning/10-projects/02-todo-list/todo/storage.go
Normal file
308
golang-learning/10-projects/02-todo-list/todo/storage.go
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
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)
|
||||
}
|
Reference in New Issue
Block a user