微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

转到模板列表变量以从模板替换

如何解决转到模板列表变量以从模板替换

所以我使用的是 go 模板,我希望能够通过从模板中获取变量列表来动态生成配置映射。

准确地说,假设我有一个看起来像这样的文件test.yaml.tmpl

car:
  color: {{ .color }}
  model: {{ .model }}

我希望能够在我的 go 代码生成一个包含 [color model][.color .model] 的数组,我可以自己处理这些点。

我查看了不同的选项,但无法得到我想要的结果,我得到的最接近的是使用 template.Root.Nodes 提取变量值,但它并不完美,并且可能在特定条件下产生不必要的错误。>

有人有一种干净的方法生成模板变量的数组吗?

编辑 1

我尝试使用树,这给了我这种类型的输出

&{test.yaml.tmpl test.yaml.tmpl ---
car:
  color: {{ .color }}
  model: {{ .model }}
 0 ---
car:
  color: {{ .color }}
  model: {{ .model }}
[] <nil> [{8 995  45} {11 409 {{ 22} {0 0  0}] 1 [] map[] 0 0}

问题是我无法访问字段节点,访问树时可用的唯一方法是:

仍然无法获取字段列表。

编辑 2

当打印 tree.Root.Nodes 时,我得到了完整的 yaml 输出,其中包含要替换的变量:

(*parse.ActionNode)(0xc00007f1d0)({{ .color }}),(*parse.TextNode)(0xc00007f200)

解决方法

好吧,您可以使用您知道的正则表达式。 ;P

package main

import (
    "fmt"
    "regexp"
)

var fieldSearch = regexp.MustCompile(`{{ \..* }}`)

func main() {
    template := `
car:
  color: {{ .color }}
  model: {{ .model }}
`
    res := fieldSearch.FindAll([]byte(template),-1)
    for i := range res {
        // this is just for readability you can replace this with 
        // magic numbers if you want
        res[i] = res[i][len("{{ .") : len(res[i])-len(" }}")]
    }

    for _,v := range res {
        fmt.Println(string(v))
    }
}
,

好的,所以我使用@icza How to get a map or list of template 'actions' from a parsed template?发布的链接并处理返回的字符串以获得我需要的内容,结果如下:

func main() {
    node := listNodeFields(t.Tree.Root)
    var tNode []string
    for _,n := range node {
        r := n[len("{{.* .") : len(n)-len(" .*}}")]
        if strings.Contains(n,"or ") {
            r = r + " or"
        }
        tNode = append(tNode,r)
    }

    config := make(map[string]string)
    for _,n := range tNode {
        var value string
        var present bool
        if strings.Contains(n," or") {
            n = strings.Replace(n," or","",-1)
            value,present = os.LookupEnv(n)
            if !present {
                fmt.Println("The variable " + value + " is not set but there is a default value in template " + t.Name() + "!")
            }
        } else {
            value,present = os.LookupEnv(n)
            if !present {
                return nil,errors.New("The variable " + f + " is not set but exists in the template " + t.Name() + "!")
            }
        }
        config[n] = value
    }
}

func listNodeFields(node parse.Node) []string {
    var res []string
    if node.Type() == parse.NodeAction {
        res = append(res,node.String())
    }
    if ln,ok := node.(*parse.ListNode); ok {
        for _,n := range ln.Nodes {
            res = append(res,listNodeFields(n)...)
        }
    }
    return res
}

因为我不想在使用默认值的情况下产生错误,所以我添加了一个特定的处理,以免从模板的 missingkey=error 选项中获取错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。