golang实现函数yamlToStruct(infile,outFile)

问:

golang实现函数yamlToStruct(infile,outFile),将yaml文件格式化成golang的结构体

gpt:

要实现一个将YAML文件格式化成Golang结构体的函数,你可以使用 `yaml` 和 `reflect` 包来处理。首先,你需要使用 `yaml.Unmarshal` 函数将YAML文件解析为一个 `map[string]interface{}` 类型的数据结构。然后,你可以使用递归函数来遍历这个map并生成相应的Golang结构体定义。

以下是一个简单的实现:

```go
package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "reflect"
    "gopkg.in/yaml.v2"
)

func yamlToStruct(infile, outFile string) error {
    // 读取YAML文件内容
    yamlData, err := ioutil.ReadFile(infile)
    if err != nil {
        return err
    }

    // 解析YAML文件
    var data map[string]interface{}
    if err := yaml.Unmarshal(yamlData, &data); err != nil {
        return err
    }

    // 生成Golang结构体定义
    structCode := generateStructCode("MyStruct", data)

    // 将结构体定义写入文件
    if err := ioutil.WriteFile(outFile, []byte(structCode), 0644); err != nil {
        return err
    }

    return nil
}

func generateStructCode(structName string, data map[string]interface{}) string {
    structCode := fmt.Sprintf("type %s struct {\n", structName)

    for key, value := range data {
        // 判断值的类型
        switch v := value.(type) {
        case map[interface{}]interface{}:
            // 如果是嵌套map,则递归生成结构体定义
            nestedStruct := generateStructCode(toCamelCase(key.(string)), v)
            structCode += fmt.Sprintf("\t%s %s\n", toCamelCase(key.(string)), nestedStruct)
        default:
            // 其他类型直接生成字段定义
            structCode += fmt.Sprintf("\t%s %s\n", toCamelCase(key.(string)), reflect.TypeOf(value).String())
        }
    }

    structCode += "}\n"
    return structCode
}

func toCamelCase(s string) string {
    // 将下划线分隔的单词转换为驼峰式
    result := ""
    upper := true

    for _, c := range s {
        if c == '_' {
            upper = true
        } else {
            if upper {
                result += string(c - ('a' - 'A'))
                upper = false
            } else {
                result += string(c)
            }
        }
    }

    return result
}

func main() {
    // 替换为你的YAML文件路径和输出文件路径
    infile := "example.yaml"
    outFile := "output.go"

    err := yamlToStruct(infile, outFile)
    if err != nil {
        log.Fatal(err)
    }
}
```

在这个例子中,`yamlToStruct` 函数接受输入的YAML文件路径和输出的Golang文件路径。它首先读取YAML文件,然后使用 `yaml.Unmarshal` 函数将其解析为一个 `map[string]interface{}`。接着,它调用 `generateStructCode` 函数生成Golang结构体的定义,并将生成的代码写入到输出文件中。 `toCamelCase` 函数用于将下划线分隔的字段名转换为驼峰式。请注意,这个实现是一个简单的示例,可能需要根据实际情况进行调整。

调整后的代码:

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"reflect"

	"gopkg.in/yaml.v2"
)

func append(structName string) string {
	upName := toCamelCase(structName)
	data := fmt.Sprintf(`
	var g_%s *%s

func Get%s() *%s {
	if g_%s != nil {
		return g_%s
	}
	yamlData, err := ioutil.ReadFile("assets/yaml/%s.yaml")
	if err != nil {
		return nil
	}
	g_%s = new(%s)
	if err := yaml.Unmarshal(yamlData, g_%s); err != nil {
		return nil
	}
	return g_%s
}`, upName, upName, upName, upName, upName, upName, structName, upName, upName, upName, upName)
	return data
}
func yamlToStruct(infile, outFile string, structName string) error {
	// 读取YAML文件内容
	yamlData, err := ioutil.ReadFile(infile)
	if err != nil {
		return err
	}

	// 解析YAML文件
	var data map[interface{}]interface{}
	if err := yaml.Unmarshal(yamlData, &data); err != nil {
		return err
	}

	// 生成Golang结构体定义
	structCode := generateStructCode(toCamelCase(structName), data, 1)

	// 将结构体定义写入文件
	if err := ioutil.WriteFile(outFile, []byte("package yaml\n"+structCode+append(structName)), 0644); err != nil {
		return err
	}

	return nil
}

func generateStructCode(structName string, data map[interface{}]interface{}, deep int) string {
	structCode := fmt.Sprintf("%s struct {\n", structName)
	switch deep {
	case 1:
		structCode = fmt.Sprintf("type %s struct {\n", structName)
	case 2: //数组
		structCode = fmt.Sprintf("struct{\n")
	default:
	}

	for key, value := range data {
		// Check if key is a string
		keyStr, ok := key.(string)
		if !ok {
			// Handle the case where key is not a string (e.g., if YAML has non-string keys)
			log.Printf("Skipping key %v of non-string type\n", key)
			continue
		}

		// Determine the type of the value
		switch v := value.(type) {
		case []interface{}:
			// If it's an array, check if it's headers
			if len(v) > 0 {
				// Check if the first element is a map
				if headerMap, ok := v[0].(map[interface{}]interface{}); ok {
					// If it's headers, generate struct code for Header type
					headerStruct := generateStructCode(toCamelCase(keyStr), headerMap, 2)
					structCode += fmt.Sprintf("\t%s []%s `yaml:\"%s\"`\n", toCamelCase(keyStr), headerStruct, keyStr)
					continue
				}
				if _, ok := v[0].(string); ok {
					// If it's headers, generate struct code for Header type
					structCode += fmt.Sprintf("\t%s []%s `yaml:\"%s\"`\n", toCamelCase(keyStr), "string", keyStr)
					continue
				}
			}

			// If it's a regular array, generate struct code for its elements
			nestedStruct := generateStructCode(toCamelCase(keyStr), v[0].(map[interface{}]interface{}), 2)
			structCode += fmt.Sprintf("\t%s []%s `yaml:\"%s\"`\n", toCamelCase(keyStr), nestedStruct, keyStr)
		case map[interface{}]interface{}:
			// If it's a nested map, recursively generate struct code
			nestedStruct := generateStructCode(toCamelCase(keyStr), v, 0)
			//structCode += fmt.Sprintf("\t%s %s `yaml:\"%s\"`\n", toCamelCase(keyStr), nestedStruct, keyStr)
			structCode += fmt.Sprintf("\t%s `yaml:\"%s\"`\n", nestedStruct, keyStr)
		default:
			// For other types, generate field definition with yaml tag
			structCode += fmt.Sprintf("\t%s %s `yaml:\"%s\"`\n", toCamelCase(keyStr), reflect.TypeOf(value).String(), keyStr)
		}
	}

	structCode += "}"
	return structCode
}

func toCamelCase(s string) string {
	// 将下划线分隔的单词转换为驼峰式
	result := ""
	upper := true

	for _, c := range s {
		if c == '_' {
			upper = true
		} else {
			if upper {
				result += string(c - ('a' - 'A'))
				upper = false
			} else {
				result += string(c)
			}
		}
	}

	return result
}

func main() {
	// 替换为你的YAML文件路径和输出文件路径
	var fileName string
	fmt.Print("Path is assets/yaml and Enter the input YAML file name: ")
	fmt.Scanln(&fileName)
	infile := "assets/yaml/" + fileName + ".yaml"
	outFile := "assets/yaml/" + fileName + ".go"

	err := yamlToStruct(infile, outFile, fileName)
	if err != nil {
		log.Fatal(err)
	} else {
		log.Printf("make success")
	}
}

  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Go语言Golang)是一种开源的编程语言,它具有简洁、高效和并发性强的特点。在Go语言中,函数是一等公民,可以像其他类型的值一样进行传递和操作。 下面是介绍Golang实现函数的几个关键点: 1. 函数定义:使用关键字`func`来定义函数,语法如下: ``` func 函数名(参数列表) 返回值列表 { // 函数体 } ``` 例如,定义一个计算两个整数之和的函数: ``` func add(a, b int) int { return a + b } ``` 2. 函数参数:函数可以接受零个或多个参数,参数之间用逗号分隔。参数可以指定类型,例如`a, b int`表示两个整数类型的参数。如果多个参数的类型相同,可以只在最后一个参数后面指定类型。 例如,定义一个计算两个整数之差的函数: ``` func subtract(a, b int) int { return a - b } ``` 3. 函数返回值:函数可以返回一个或多个值。返回值列表放在函数名后面的括号中,并指定返回值的类型。如果函数没有返回值,可以省略返回值列表。 例如,定义一个计算两个整数之积和商的函数: ``` func multiplyAndDivide(a, b int) (int, float64) { return a * b, float64(a) / float64(b) } ``` 4. 匿名函数:在Go语言中,可以使用匿名函数,即没有函数名的函数。匿名函数可以直接赋值给变量,也可以作为参数传递给其他函数。 例如,定义一个匿名函数并将其赋值给变量: ``` add := func(a, b int) int { return a + b } ``` 5. 函数作为参数和返回值:在Go语言中,函数可以作为参数传递给其他函数,也可以作为函数的返回值。 例如,定义一个接受函数作为参数的函数: ``` func operate(a, b int, operation func(int, int) int) int { return operation(a, b) } ``` 以上是Golang实现函数的基本介绍。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值