Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variables in nested golang templates

Tags:

templates

go

I want to define variables inside of a golang template, instead of in a binary so that there is no need to recompile.

In Go, I set some vars:

var animals = map[string]string{
    "spirit_animal":    "cat",
    "spirit_predator":  "dog",
}

I execute the template with this: t.ExecuteTemplate(w, "main", variables) which passes these vars to the template.

Now I would like to take these vars from go and into the "main" template.

{{$spirit_animal:="cat"}} {{$spirit_animal}}

And I call sub-templates like this:

{{ template "navbar" . }}

The problem is that nested templates (sub templates) do not appear to have access to any variables.

From the documentation, "A template invocation does not inherit variables from the point of its invocation." Reading the Documentation for "text/template", it sounds like variables may not be able to be used in nested templates.

Any suggestions on how to get these vars out of a binary and into a single text location accessible by nested templates that doesn't need to be recompiled on change?

like image 254
Zamicol Avatar asked Aug 31 '16 16:08

Zamicol


1 Answers

You can indeed! You just need to pass in variables into the nested template.

The documentation you cited is about how the template can't read variables in from the go process, unless you explicitly pass them in.

Similarly, nested templates will take whatever you pass them and nothing more.

From https://golang.org/pkg/text/template/#hdr-Actions

{{template "name"}}
    The template with the specified name is executed with nil data.

{{template "name" pipeline}}
    The template with the specified name is executed with dot set
    to the value of the pipeline.

Here's a quick example lightly based on your prompt:

package main

import (
    "os"
    "text/template"
)

func main() {
    var animals = map[string]string{
        "spirit_animal":   "cat",
        "spirit_predator": "dog",
    }

    const letter = `
{{define "echo"}}Inside a template, I echo what you say: {{.}}{{end}}
{{define "predator"}}Inside a template, I know that your predator is: {{.spirit_predator}}{{end}}

Your spirit animal is: {{.spirit_animal}}

{{template "predator" . }}

{{template "echo" .spirit_animal }}`

    t := template.Must(template.New("letter").Parse(letter))
    _ = t.Execute(os.Stdout, animals)
}

https://play.golang.org/p/3X7IQasWlsR

like image 109
Liyan Chang Avatar answered Nov 10 '22 19:11

Liyan Chang