Iterate through map in Go text template

huangapple go评论84阅读模式
英文:

Iterate through map in Go text template

问题

我有一个值的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

而且即使它能工作,逗号也是不正确的。然后我尝试使用自定义函数来格式化该map,但我无法让模板调用我的函数。以下任何一种似乎都不起作用:

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

谢谢!

英文:

I have a map of values that looks like this:

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

What should my template look like to generate the following string (note the correct comma usage)?

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

I started with this as my template:

SET {{range $i, $v := .values}} {{.bat}}.{{$i}}={{$v}},{{end}}

But that just prints out

SET

And even if that did work, the commas would be incorrect. I then tried to use a custom function to format the map, but I couldn't get the template to ever call my function. None of the following seemed to work:

SET {{.MyFunction .values}}
SET {{call .MyFunction .values}}
SET {{call MyFunction .values}}

when MyFunction was defined as:

func MyFunction(data map[string]interface{}) string {
  fmt.PrintLn('i was called!')
  return "foo"
}

And I'm executing the templates using a helper function that looks like this:

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

Thanks!

答案1

得分: 3

这将让你接近目标:

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

渲染结果为:

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

不幸的是,由于range操作在映射上的迭代方式(没有数值索引),我认为没有简单的方法在值之间添加逗号。尽管如此,template包的设计初衷是为了方便扩展,这样你就可以在模板中减少逻辑,将更多的逻辑放在Go代码中,因此很容易在Go中编写一个辅助函数,并将其提供给模板使用。

如果你愿意额外努力,那么模板会变得更简单,而且效率更高。辅助函数可以像这样:

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

这里有一个使用这个逻辑的可工作示例:

英文:

This will get you pretty close:

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

rendering as:

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:

huangapple
  • 本文由 发表于 2013年9月11日 05:01:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/18728682.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定