Search code examples
gotemplatesvariablesdynamicgomplate

Go Template get a variable dynamically


I have yml parameters that look like

nodes: one, two
instanceMinOne: 1
instanceMaxOne: 2
instanceMinTwo: 4
instanceMaxTwo: 6

Is there a way with go templating to dynamically read for example instanceMinOne where the variable name is composed of instanceMin + the dynamic value coming from the nodes list ?

something like (this obviously doesn't work but just give the idea of what I'd like to achieve)

{{ - range $nodeName := (split .Parameters.nodes) } } } }
   instance-min: {{ .Parameters.instanceMin$nodeName }}
   instance-max: {{ .Parameters.instanceMan$nodeName }}
{{ - end }}

Solution

  • To achieve what you want, you have to solve 2 tasks:

    • string concatenation
    • indexing with a dynamic value

    For concatenation you may use the builtin print function, e.g.

    {{ $key := print "instanceMin" $nodeName }}
    

    For indexing, use the builtin index function:

    instance-min: {{ index $.Parameters $key }}
    

    (Note: The {{range}} action changes the dot, so inside it you need $ to reference outside of the loop variable.)

    Or in one line:

    instance-min: {{ index $.Parameters (print "instanceMin" $nodeName) }}
    

    See a runnable demo:

    func main() {
        t := template.Must(template.New("").Parse(src))
    
        params := map[string]any{
            "Parameters": map[string]any{
                "nodes":          []string{"One", "Two"},
                "instanceMinOne": 1,
                "instanceMaxOne": 2,
                "instanceMinTwo": 4,
                "instanceMaxTwo": 6,
            },
        }
    
        if err := t.Execute(os.Stdout, params); err != nil {
            panic(err)
        }
    }
    
    const src = `{{- range $idx, $nodeName := .Parameters.nodes }}
       instance-min: {{ index $.Parameters (print "instanceMin" $nodeName) }}
       instance-max: {{ index $.Parameters (print "instanceMax" $nodeName) }}
    {{- end }}`
    

    This will output (try it on the Go Playground):

    instance-min: 1
    instance-max: 2
    instance-min: 4
    instance-max: 6