소스 검색

修改toml解析为viper库

GTong 7 달 전
부모
커밋
24d6d464ab
3개의 변경된 파일164개의 추가작업 그리고 20개의 파일을 삭제
  1. 114 0
      internal/middleware/cache copy.go
  2. 46 19
      internal/middleware/cache.go
  3. 4 1
      internal/middleware/test/cache_test.go

+ 114 - 0
internal/middleware/cache copy.go

@@ -0,0 +1,114 @@
+package middleware
+
+// import (
+// 	"fmt"
+// 	"os"
+// 	"path/filepath"
+// 	"regexp"
+// 	"sort"
+// 	"xg_dba/internal/models"
+
+// 	"github.com/BurntSushi/toml"
+// )
+
+// func InitCache(folderPath string) {
+
+// 	packageModels := make(map[string]models.Cache)
+
+// 	err := filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error {
+// 		if err != nil {
+// 			return err
+// 		}
+
+// 		if info.IsDir() {
+// 			listenFilePath := filepath.Join(path, "listen.toml")
+
+// 			var connectInfo models.ConnectInfo
+// 			var systemMetaInfo models.SystemMetaInfo
+
+// 			if fileExists(listenFilePath) {
+// 				if _, err := parseTomlFile(listenFilePath, &connectInfo); err != nil {
+// 					return err
+// 				}
+// 			}
+
+// 			latestOsInfoFilePath, err := getLatestOsInfoFile(path)
+// 			if err != nil {
+// 				return err
+// 			}
+
+// 			if latestOsInfoFilePath != "" {
+// 				if _, err := parseTomlFile(latestOsInfoFilePath, &systemMetaInfo); err != nil {
+// 					return err
+// 				}
+// 			}
+
+// 			host := connectInfo.Ssh.Host
+// 			if host != "" {
+// 				packageModels[host] = models.Cache{
+// 					ConnectInfo:    connectInfo,
+// 					SystemMetaInfo: systemMetaInfo,
+// 				}
+// 			}
+// 		}
+// 		return nil
+// 	})
+
+// 	if err != nil {
+// 		fmt.Printf("Error walking the path %q: %v\n", folderPath, err)
+// 		return
+// 	}
+
+// 	for host, cache := range packageModels {
+// 		fmt.Printf("Host: %s, Cache: %+v\n", host, cache)
+// 	}
+// 	fmt.Println("个数为: ", len(packageModels))
+// }
+
+// func fileExists(filename string) bool {
+// 	info, err := os.Stat(filename)
+// 	if os.IsNotExist(err) {
+// 		return false
+// 	}
+// 	return !info.IsDir()
+// }
+
+// func parseTomlFile(filePath string, v interface{}) (toml.MetaData, error) {
+// 	file, err := os.Open(filePath)
+// 	if err != nil {
+// 		return toml.MetaData{}, err
+// 	}
+// 	defer file.Close()
+
+// 	decoder := toml.NewDecoder(file)
+// 	metaData, err := decoder.Decode(v)
+// 	if err != nil {
+// 		return toml.MetaData{}, err
+// 	}
+// 	return metaData, nil
+// }
+
+// func getLatestOsInfoFile(dirPath string) (string, error) {
+// 	pattern := regexp.MustCompile(`^os_info(?:_\d{8}_\d{6})?\.toml$`)
+// 	files, err := os.ReadDir(dirPath)
+// 	if err != nil {
+// 		return "", err
+// 	}
+
+// 	var matchingFiles []string
+// 	for _, file := range files {
+// 		if !file.IsDir() && pattern.MatchString(file.Name()) {
+// 			matchingFiles = append(matchingFiles, filepath.Join(dirPath, file.Name()))
+// 		}
+// 	}
+
+// 	if len(matchingFiles) == 0 {
+// 		return "", nil
+// 	}
+
+// 	sort.Slice(matchingFiles, func(i, j int) bool {
+// 		return matchingFiles[i] > matchingFiles[j]
+// 	})
+
+// 	return matchingFiles[0], nil
+// }

+ 46 - 19
internal/middleware/cache.go

@@ -8,14 +8,12 @@ import (
 	"sort"
 	"xg_dba/internal/models"
 
-	"github.com/BurntSushi/toml"
+	"github.com/mitchellh/mapstructure"
+	"github.com/spf13/viper"
 )
 
-func Cache() {
-
-	// 指定需要查找的根文件夹路径
-	folderPath := "C:\\Program_GT\\Code\\Go\\Work\\xugu\\xg_dba\\config"
-
+// InitCache 初始化缓存,从指定目录中读取 TOML 文件内容并存储到 packageModels 映射中。
+func InitCache(folderPath string) {
 	packageModels := make(map[string]models.Cache)
 
 	err := filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error {
@@ -29,23 +27,27 @@ func Cache() {
 			var connectInfo models.ConnectInfo
 			var systemMetaInfo models.SystemMetaInfo
 
+			// 如果 listen.toml 文件存在,解析它到 connectInfo 结构体中
 			if fileExists(listenFilePath) {
-				if _, err := parseTomlFile(listenFilePath, &connectInfo); err != nil {
+				if err := parseTomlFile(listenFilePath, &connectInfo); err != nil {
 					return err
 				}
 			}
 
+			// 获取目录中最新的 os_info.toml 文件
 			latestOsInfoFilePath, err := getLatestOsInfoFile(path)
 			if err != nil {
 				return err
 			}
 
+			// 如果找到最新的 os_info.toml 文件,解析它到 systemMetaInfo 结构体中
 			if latestOsInfoFilePath != "" {
-				if _, err := parseTomlFile(latestOsInfoFilePath, &systemMetaInfo); err != nil {
+				if err := parseTomlFile(latestOsInfoFilePath, &systemMetaInfo); err != nil {
 					return err
 				}
 			}
 
+			// 使用主机地址作为键,将解析的信息存储到 packageModels 映射中
 			host := connectInfo.Ssh.Host
 			if host != "" {
 				packageModels[host] = models.Cache{
@@ -58,15 +60,17 @@ func Cache() {
 	})
 
 	if err != nil {
-		fmt.Printf("Error walking the path %q: %v\n", folderPath, err)
+		fmt.Printf("遍历路径 %q 时出错: %v\n", folderPath, err)
 		return
 	}
 
+	// 打印每个主机的缓存数据
 	for host, cache := range packageModels {
-		fmt.Printf("Host: %s, Cache: %+v\n", host, cache)
+		fmt.Printf("主机: %s, 缓存: %+v\n", host, cache)
 	}
 }
 
+// fileExists 检查给定路径的文件是否存在。
 func fileExists(filename string) bool {
 	info, err := os.Stat(filename)
 	if os.IsNotExist(err) {
@@ -75,21 +79,42 @@ func fileExists(filename string) bool {
 	return !info.IsDir()
 }
 
-func parseTomlFile(filePath string, v interface{}) (toml.MetaData, error) {
-	file, err := os.Open(filePath)
-	if err != nil {
-		return toml.MetaData{}, err
+// parseTomlFile 使用 viper 解析 TOML 文件到提供的结构体中。
+func parseTomlFile(filePath string, v interface{}) error {
+	// 为了防止 viper 的全局状态干扰解析结果,使用新的 viper 实例
+	vp := viper.New()
+	vp.SetConfigFile(filePath)
+	vp.SetConfigType("toml")
+
+	if err := vp.ReadInConfig(); err != nil {
+		return err
 	}
-	defer file.Close()
 
-	decoder := toml.NewDecoder(file)
-	metaData, err := decoder.Decode(v)
+	// 使用 `vp.AllSettings()` 将配置映射到提供的结构体
+	settings := vp.AllSettings()
+	if err := decodeSettings(settings, v); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// decodeSettings 将 viper 的设置映射解码到目标结构体。
+func decodeSettings(settings map[string]interface{}, v interface{}) error {
+	decoderConfig := &mapstructure.DecoderConfig{
+		Result:           v,
+		TagName:          "toml",
+		WeaklyTypedInput: true,
+	}
+	decoder, err := mapstructure.NewDecoder(decoderConfig)
 	if err != nil {
-		return toml.MetaData{}, err
+		return err
 	}
-	return metaData, nil
+	return decoder.Decode(settings)
 }
 
+// getLatestOsInfoFile 在给定目录中查找最新的 os_info TOML 文件。
+// 它查找匹配模式 "os_info_<timestamp>.toml" 的文件,并返回最新的一个。
 func getLatestOsInfoFile(dirPath string) (string, error) {
 	pattern := regexp.MustCompile(`^os_info(?:_\d{8}_\d{6})?\.toml$`)
 	files, err := os.ReadDir(dirPath)
@@ -104,10 +129,12 @@ func getLatestOsInfoFile(dirPath string) (string, error) {
 		}
 	}
 
+	// 如果没有找到匹配的文件,返回空字符串
 	if len(matchingFiles) == 0 {
 		return "", nil
 	}
 
+	// 将匹配的文件按降序排序,以获取最新的文件
 	sort.Slice(matchingFiles, func(i, j int) bool {
 		return matchingFiles[i] > matchingFiles[j]
 	})

+ 4 - 1
internal/middleware/test/cache_test.go

@@ -6,5 +6,8 @@ import (
 )
 
 func TestCache(t *testing.T) {
-	middleware.Cache()
+
+	// 指定需要查找的根文件夹路径
+	folderPath := "C:\\Program_GT\\Code\\Go\\Work\\xugu\\xg_dba\\config"
+	middleware.InitCache(folderPath)
 }