2

我有一个map看起来像这样的值:

vals := map[string]interface{}{"foo": 1, "bar": 2, "baz": 7}
data := map[string]interface{}{"bat": "obj", "values": vals}

我的模板应该是什么样子才能生成以下字符串(注意正确的逗号用法)?

SET obj.foo=1, obj.bar=2, obj.baz=7

我从这个作为我的模板开始:

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"
}

我正在使用如下所示的辅助函数执行模板:

func useTemplate(name string, data interface{}) string {
  out := new(bytes.Buffer)
  templates[name].Execute(out, data)
  return string(out.Bytes())
}

谢谢!

4

1 回答 1

3

这将使您非常接近:

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

呈现为:

SET obj.bar=2 obj.baz=7 obj.foo=1

Unfortunately, I don't think there's any simple way to have the commas added in between the values due to how the range action iterates on maps (there's no numeric index). That said, the template packages were meant to be easily extensible so you can have less logic in your templates and more logic in Go itself, so it's easy enough to code a helper function in Go and make it available to your templates.

If you're happy to go that extra mile, then the template becomes much simpler, and also more efficient. The function can look like this:

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()
}

and your template would look like:

SET {{$.values | commaJoin $.bat}}

Here is a working example with this logic:

于 2013-09-10T22:19:49.337 回答