遍历Go文本模板中的映射

遍历Go文本模板中的映射,go,go-templates,Go,Go Templates,我有一个值映射,如下所示: vals := map[string]interface{}{"foo": 1, "bar": 2, "baz": 7} data := map[string]interface{}{"bat": "obj", "values": vals} func useTemplate(name string, data interface{}) string { out := new(bytes.Buffer) templates[name].Execute(out

我有一个
值映射
,如下所示:

vals := map[string]interface{}{"foo": 1, "bar": 2, "baz": 7}
data := map[string]interface{}{"bat": "obj", "values": vals}
func useTemplate(name string, data interface{}) string {
  out := new(bytes.Buffer)
  templates[name].Execute(out, data)
  return string(out.Bytes())
}
func commaJoin(prefix string, m map[string]interface{}) string {
    var buf bytes.Buffer
    first := true
    for k, v := range m {
        if !first {
            buf.WriteString(", ")
        }
        first = false
        buf.WriteString(prefix)
        buf.WriteByte('.')
        buf.WriteString(k)
        buf.WriteByte('=')
        buf.WriteString(fmt.Sprint(v))
    }
    return buf.String()
}
生成以下字符串时,我的模板应该是什么样子的(请注意正确的逗号用法)

我首先将此作为我的模板:

SET {{range $i, $v := .values}} {{.bat}}.{{$i}}={{$v}},{{end}}
但那只是打印出来的

SET
即使这样做有效,逗号也是不正确的。然后,我尝试使用自定义函数格式化映射,但我无法让模板调用我的函数。以下各项似乎都不起作用:

SET {{.MyFunction .values}}
SET {{call .MyFunction .values}}
SET {{call MyFunction .values}}
当MyFunction被定义为:

func MyFunction(data map[string]interface{}) string {
  fmt.PrintLn('i was called!')
  return "foo"
}
我正在使用一个助手函数执行模板,该函数如下所示:

vals := map[string]interface{}{"foo": 1, "bar": 2, "baz": 7}
data := map[string]interface{}{"bat": "obj", "values": vals}
func useTemplate(name string, data interface{}) string {
  out := new(bytes.Buffer)
  templates[name].Execute(out, data)
  return string(out.Bytes())
}
func commaJoin(prefix string, m map[string]interface{}) string {
    var buf bytes.Buffer
    first := true
    for k, v := range m {
        if !first {
            buf.WriteString(", ")
        }
        first = false
        buf.WriteString(prefix)
        buf.WriteByte('.')
        buf.WriteString(k)
        buf.WriteByte('=')
        buf.WriteString(fmt.Sprint(v))
    }
    return buf.String()
}

谢谢

这将使您非常接近:

SET {{range $key, $value := $.values}}{{$.bat}}.{{$key}}={{$value}} {{end}}
呈现为:

SET obj.bar=2 obj.baz=7 obj.foo=1
不幸的是,我不认为有任何简单的方法可以在值之间添加逗号,因为
范围
操作在地图上是如何迭代的(没有数字索引)。这就是说,
template
包的目的是易于扩展,这样您可以在模板中使用更少的逻辑,而在Go中使用更多的逻辑,因此在Go中编写一个helper函数并使其可用于模板非常容易

如果您愿意多做一点,那么模板就会变得更简单,也更高效。该函数可以如下所示:

vals := map[string]interface{}{"foo": 1, "bar": 2, "baz": 7}
data := map[string]interface{}{"bat": "obj", "values": vals}
func useTemplate(name string, data interface{}) string {
  out := new(bytes.Buffer)
  templates[name].Execute(out, data)
  return string(out.Bytes())
}
func commaJoin(prefix string, m map[string]interface{}) string {
    var buf bytes.Buffer
    first := true
    for k, v := range m {
        if !first {
            buf.WriteString(", ")
        }
        first = false
        buf.WriteString(prefix)
        buf.WriteByte('.')
        buf.WriteString(k)
        buf.WriteByte('=')
        buf.WriteString(fmt.Sprint(v))
    }
    return buf.String()
}
您的模板将如下所示:

SET {{$.values | commaJoin $.bat}}
下面是一个使用此逻辑的工作示例:


啊,这就是正确调用函数的方式。非常好用,谢谢@Gustavo,在这里使用管道而不是简单的函数调用有什么好处?我建议改为使用“SET{{{commaJoin$.bat$.values}}”,因为这更容易理解。我倾向于将格式化逻辑作为管道编写,因为它似乎更容易发现正在格式化的内容,但这是一个偏好问题。