【问题标题】:Convert a generic map to YAML. GoLang将通用映射转换为 YAML。语言
【发布时间】:2020-09-24 02:27:57
【问题描述】:

所以,我正在开发一个程序,您必须在其中生成 YAML 文件,该文件表示来自给定目录位置的目录树 (path)。比如……

sc
├── file.go
├── file_test.go
└── src
    ├── deploy
    │   ├── deploy.go
    │   └── deploy_test.go
    ├── pod.go
    └── pod_test.go

这应该转换成

sc:
  fileTest: "true"
  src:
    deploy:
      deployTest: "true"
  podTest: "true"

请注意,上面只选择了带有_test 的文件(这是有条件的,问题不大)。我的问题是如何从可以通过 YAML 表示的目录树中生成通用的 map[string]interface{} 类型的映射。我尝试编写DFS 实现来遍历树并生成n-ary 树。其中有以下输出。我得到了树的根 Node 对象。

name: sc
children:
- name: file.go
  children: []
- name: file_test.go
  children: []
- name: src
  children:
  - name: deploy
    children:
    - name: deploy.go
      children: []
    - name: deploy_test.go
      children: []
  - name: pod.go
    children: []
  - name: pod_test.go
    children: []

但正如您所见,它是unmarshalled,使用代表每个节点的数据类型。

//Node is the datatype which stores information regarding the file/directory
type Node struct {
    Name     string
    Path     string
    Children []*Node
}

我想要一个通用的 YAML,其中每个键都不同。有任何想法吗?这样的事情会有所帮助。

func (node *Node) ToMap() map[string]interface{}{
 //Logic
}

生成树的 DFS 代码

func IteratePath(path string) {
    rootFile, err := os.Stat(path)
    if err != nil {
        logrus.Error("Path : ", path, " doesn't exist. ", err)
    }
    rootfile := ToFile(rootFile, path)
    stack := []*tree.Node{rootfile}
    for len(stack) > 0 {
        file := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        children, _ := ioutil.ReadDir(file.Path)
        for _, chld := range children {
            child := ToFile(chld, filepath.Join(file.Path, chld.Name()))
            file.Children = append(file.Children, child)
            stack = append(stack, child)
        }
    }

func ToFile(file os.FileInfo, path string) *tree.Node {
    outFile := tree.Node{
        Name:     file.Name(),
        Children: []*tree.Node{},
        Path:     path,
    }
    return &outFile
}

【问题讨论】:

    标签: go data-structures interface hashmap yaml


    【解决方案1】:

    您已经在使用递归(使用堆栈变量而不是调用堆栈),那么为什么不再次使用递归将您的树转换为嵌套映射。这是我写的一个从节点开始的方法(基于你上面的Node 结构):

    树到嵌套映射方法:

    type Node struct {
        Name     string
        Children []*Node
    }
    
    func (n *Node) ToMap() interface{} {
        if len(n.Children) < 1 {
            return "true"
        }
    
        yamlMap := make(map[string]interface{})
    
        for _, child := range n.Children {
            yamlMap[child.Name] = child.ToMap()
        }
    
        return yamlMap
    }
    

    此函数生成的映射可由gopkg.in/yaml.v2 编组为所需格式的 YAML 文件。

    这是在 Go Playground 中运行的代码,包括编组到 YAML

    【讨论】:

    • 谢谢,这在使用一组值构建地图方面是有意义的,但我有兴趣拥有一个通用实现,其中 YAML 可以通过使用我们说的目录路径来构建。或者从树的根节点。例如,这样的事情会有所帮助。 func (node *Node) ToMap() map[string]interface{}。我对可以构建该地图的方法感兴趣。稍后可以将其编组为 YAML。
    • 更新了问题以添加用于遍历和构建的 DFS 代码。
    • 感谢您分享您的代码。我更新了我的答案,加入了一个函数,可以从你拥有的树中生成嵌套的地图结构。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-17
    • 2015-08-04
    相关资源
    最近更新 更多