package yaml_loader import ( "bytes" "fmt" "github.com/pkg/errors" "gopkg.in/yaml.v3" "io" "os" "reflect" ) type LoadMapCallback func(objectMap map[string]any) error // LoadYamlFile 加载YAML文件,一个文件中可以有多个YAML对象 // 参数: // yamlFilePath: YAML文件路径 // retObjects: 用来接收YAML对象的指针或者map的slice // 返回值: // 错误 func LoadYamlFile(yamlFilePath string, retObjects *[]any) error { yamlFile, err := os.Open(yamlFilePath) if err != nil { return err } defer func(yamlFile *os.File) { err := yamlFile.Close() if err != nil { fmt.Println(err) } }(yamlFile) return loadYaml(yamlFile, retObjects) } // LoadYamlBytes 加载YAML文件字节,一个文件中可以有多个YAML对象 // 参数: // yamlBytes: YAML文件的字节 // retObjects: 用来接收YAML对象的指针或者map的slice // 返回值: // 错误 func LoadYamlBytes(yamlBytes []byte, retObjects *[]any) error { return loadYaml(bytes.NewReader(yamlBytes), retObjects) } // LoadYamlMapFile 加载YAML文件,一个文件中可以有多个YAML对象,顶级不能是YAML数组 // 参数: // yamlFilePath: YAML文件路径 // callback: 回调函数 // 返回值: // 错误 func LoadYamlMapFile(yamlFilePath string, callback LoadMapCallback) error { yamlFile, err := os.Open(yamlFilePath) if err != nil { return err } defer func(yamlFile *os.File) { err := yamlFile.Close() if err != nil { fmt.Println(err) } }(yamlFile) return loadYamlMap(yamlFile, callback) } // LoadYamlMapBytes 加载YAML文件字节,一个文件中可以有多个YAML对象,顶级不能是YAML数组 // 参数: // yamlBytes: YAML文件的字节 // callback: 回调函数 // 返回值: // 错误 func LoadYamlMapBytes(yamlBytes []byte, callback LoadMapCallback) error { return loadYamlMap(bytes.NewReader(yamlBytes), callback) } func loadYaml(r io.Reader, retObjects *[]any) error { decoder := yaml.NewDecoder(r) for i := 0; i < len(*retObjects); i++ { retObject := (*retObjects)[i] retObjectType := reflect.TypeOf(retObject) if retObjectType.Kind() != reflect.Ptr && retObjectType.Kind() != reflect.Map { return errors.New("返回对象slice需要指针或者map") } err := decoder.Decode(retObject) if err != nil { if err == io.EOF { break } return err } } return nil } func loadYamlMap(r io.Reader, callback LoadMapCallback) error { decoder := yaml.NewDecoder(r) for { object := make(map[string]any) err := decoder.Decode(object) if err != nil { if err == io.EOF { break } return err } err = callback(object) if err != nil { return err } } return nil }