Home > Mobile >  Golang Templates - Update and Print Counter Variable
Golang Templates - Update and Print Counter Variable

Time:10-28

I am trying to update and print a counter variable inside of a Go template when iterating through a nested for loop.

I am not trying to print the index of either of my data structures as I loop through. I am not going to print every object in each data structure, and I want this counter variable to only increment when an equality statement is true.

What am I doing wrong here?

Go Playground link: https://play.golang.org/p/RsuEk1PqZ7a

type a struct {
    Numbers []string
    Letters []string
}

var data = &a{
    Numbers: []string{"one", "two"},
    Letters: []string{"a","b","b", "c"},
}

var tmplSrc = `start
{{with $i := 0}}
  {{range $number := .Numbers}}
    {{range $letter := .Letters}}
      {{if eq $letter "b"}}
        {{$i = add $i 1}}
        {{$i}}
      {{end}}
    {{end}}
  {{end}}
{{end}}
fin
`

func main() {
    funcMap := template.FuncMap{
        "add": func(a int, b int) int {
            return a   b
        },
    }
    tmpl := template.Must(template.New("test").Funcs(funcMap).Parse(tmplSrc))
    tmpl.Execute(os.Stdout, data)
}

CodePudding user response:

The error returned from tmpl.Execute execute hints at the problem:

test:3:21: executing "test" at <.Numbers>: can't evaluate field Numbers in type int

Always handle errors!

The problem is that {{with $i := 0}} sets . to the 0. The template expects . to be the data argument to the template. Fix by using $ to refer to the data argument. A similar change is required for .Letters because {{range}} also sets ..

{{with $i := 1}}
  {{range $number := $.Numbers}}
    {{range $letter := $.Letters}}
    {{if eq $letter "b"}}
      {{$i = add $i 1}}
      {{$i}}
    {{end}}
    {{end}}
  {{end}}
{{end}}

I used {{with $i := 1}} to match the code in the playground. The question uses {{with $i := 0}}. The code in the question introduces yet another problem: the contents of the {{with}} is skipped because the condition evaluates to false (0 is false in template conditions). Fix by removing the {{with}} directive. It's not needed.

{{$i := 0}}
{{range $number := $.Numbers}}
  {{range $letter := $.Letters}}
    {{if eq $letter "b"}}
      {{$i = add $i 1}}
        {{$i}}
     {{end}}
  {{end}}
{{end}}
  • Related