How to parse multiple strings into a template with Go?
Asked Answered
H

2

6

Is there a simple way like template.ParseFiles("base.html", "home.html") but for strings to build a template from a set of strings?

I have a base template and a list of pages templates (all as strings) that I want to build on top of base template.

I figured out how to merge them, but I my solution is quite verbose and doesn't look elegant enough, even though working.

Holyhead answered 25/1, 2017 at 15:55 Comment(0)
M
7

You may create a new, empty template using template.New() function. Then you may use the Template.New() method to create a new, empty, associated template. And you may parse "into" this using the Template.Parse() method.

Here's how it could look like:

func parseTemplates(templs ...string) (t *template.Template, err error) {
    t = template.New("_all")

    for i, templ := range templs {
        if _, err = t.New(fmt.Sprint("_", i)).Parse(templ); err != nil {
            return
        }
    }

    return
}

Testing it:

t, err := parseTemplates(
    `{{define "one"}}I'm #1.{{end}}`,
    `{{define "two"}}I'm #2, including #1: {{template "one" .}}{{end}}`,
)
if err != nil {
    panic(err)
}

if err = t.ExecuteTemplate(os.Stdout, "two", nil); err != nil {
    panic(err)
}

Output (try it on the Go Playground):

I'm #2, including #1: I'm #1.

Also see related question: Go template name

Note

While we could call the Template.Parse() method on a single template multiple times, and it would parse multiple named templates properly, it is still advisable to acquire a new template.Template for each by calling Template.New(). Because if the template texts have content outside of named templates, they will be overwritten and only the last would be retained. For example: abc {{define "one"}}no 1{{end}}. The static text "abc" would be lost by a subsequent Template.Parse() call.

This is also noted in the doc of Template.Parse():

(In multiple calls to Parse with the same receiver template, only one call can contain text other than space, comments, and template definitions.)

Maisey answered 25/1, 2017 at 16:11 Comment(0)
H
0

Maybe

for _, templ := range ListOfPagesTemplates{
    YourBaseTemplate.Parse(templ)
}

err check absent for simplicity of reading

Heldentenor answered 25/1, 2017 at 16:16 Comment(2)
While this may be used to parse multiple named templates, without acquiring a new template.Template for each by calling Template.New(), if the template texts have content outside of named templates, they will be overwritten and only the last will be retained. Example: abc {{define "one"}}no 1{{end}}. The static text "abc" would be lost by a subsequent Parse(). See my answer for details.Maisey
@Maisey Yes, your answer is more exact and detailed for sure. I only show the way it can be done.Heldentenor

© 2022 - 2024 — McMap. All rights reserved.