Last item in a Golang template range

2019-04-06 02:34发布

问题:

Given the template

{{range $i, $e := .SomeField}}
        {{if $i}}, {{end}}
        $e.TheString
{{end}}

This can output

one, two, three

If, however, I want to output

one, two, and three

I'd need to know which is the last element in the range above.

I can set a variable that holds the length of the array .SomeField, but that will always be 3, and the $i value above will only ever get to 2. And you can't perform arithmetic in templates from what I've seen.

Is detecting the last value in a template range possible? Cheers.

回答1:

This is probably not the most elegant solution but it's the best I could find:

http://play.golang.org/p/MT91mLqk1s

package main

import (
    "os"
    "reflect"
    "text/template"
)

var fns = template.FuncMap{
    "last": func(x int, a interface{}) bool {
        return x == reflect.ValueOf(a).Len() - 1
    },
}


func main() {
    t := template.Must(template.New("abc").Funcs(fns).Parse(`{{range  $i, $e := .}}{{if $i}}, {{end}}{{if last $i $}}and {{end}}{{$e}}{{end}}.`))
    a := []string{"one", "two", "three"}
    t.Execute(os.Stdout, a)
}

Note: You can also do it without reflect using the len function (credit to Russ Cox): http://play.golang.org/p/V94BPN0uKD

c.f.

  • https://groups.google.com/forum/#!topic/golang-nuts/yRXHSCjVAcM
  • https://groups.google.com/forum/#!msg/golang-nuts/XBScetK-guk/Bh7ZFz6R3wQJ
  • https://groups.google.com/forum/#!topic/golang-nuts/mqRbR7AFJj0


回答2:

We had same problem today when working with format in docker inspect command. The easiest way to get the last element without patching Docker was (the expression has been split into lines for ease of reading):

{{ $image := "" }}
{{ range split .ContainerImageName "/" }}
    {{ $image = . }}{{ end }}
{{ index (split $image ":") 0 }}

So in our case, we needed the image name without registry address and version. For example, image name like registry.domain.local/images/nginx:latest becomes nginx.

P.S: You need Go >= 1.11 to do the job (https://github.com/golang/go/issues/10608)