template Funcs and ParseFiles

2,719 views
Skip to first unread message

Keyur Shah

unread,
Aug 6, 2013, 8:57:31 PM8/6/13
to golan...@googlegroups.com
I have multiple template files (base.html, header.html, footer.html, content.html, etc.) that I pass to ParseFiles and it works as expected. Bring in Funcs however and I have never been able to successfully call my funcs from the templates when using ParseFiles:

t, _ := template.New(noNameWorks).Funcs(f).ParseFiles("a.html", "b.html", "c.html")

I've tried various names - "a.html", "b.html", "c.html","a", "b", "c", (special mention: "mercy", "@F#$%*") - but it always errors out complaining about my func being not defined.

So then I resorted to reading the files myself and calling Parse and that works:

t := template.New("LiterallyAnyNameWorks").Funcs(f)
for _, tmpl := range[]string{"a.html","b.html","c.html"} {
b, _ := ioutil.ReadFile(tmpl)
t, _ = t.Parse(string(b))
}

What name can I give to my template to get ParseFiles to work and also what's the significance of giving a name to the template?

Thanks,
Keyur


Kyle Lemons

unread,
Aug 7, 2013, 1:51:56 PM8/7/13
to Keyur Shah, golang-nuts
The name for New only matters if you directly Parse something into that template.  I usually use "".

template.New("").Funcs(f).ParseFiles("a.html", "b.html", "c.html")

should work, and if not, paste some code and the actual error message you're getting.
 
Thanks,
Keyur


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Keyur Shah

unread,
Aug 7, 2013, 2:44:03 PM8/7/13
to golan...@googlegroups.com, Keyur Shah
That didn't work. I get this error:

html/template: "" is an incomplete or empty template

Here's the code:

t, _ := template.New("").Funcs(f).ParseFiles(templatesFiles...)
t.Execute(w, data)

Reading files and parsing the file content works with "" as the template name. Here's the code:

t := template.New("").Funcs(f)

for _, tmpl := range templateFiles {
b, _ := ioutil.ReadFile(tmpl)
t, _ = t.Parse(string(b))
}

t.Execute(w, data)

Thanks,
Keyur

Carlos Castillo

unread,
Aug 7, 2013, 3:11:18 PM8/7/13
to golan...@googlegroups.com, Keyur Shah
Use ExecuteTemplate with a template name, not Execute. Execute is meant for when you parse a single template, it has some logic for when there are multiple templates, but it's not well documented, and using ParseFiles() produces a different template set that Execute handles differently than parsing one at a time.

It's almost always preferred when you have a bunch of templates in a single template "Set" to explicitly choose the one you want to render with ExecuteTemplate.

DeedleFake

unread,
Aug 7, 2013, 3:43:47 PM8/7/13
to golan...@googlegroups.com, Keyur Shah
This drove me nuts for quite a while, until I realized that there's absolutely no need to call template.New() at all; rather than defining a blank template with a random name, just use new(template.Template). This is a contrived example, but if you replace the

.New("example").Parse(tmpl)

at the end of the nasty method chain with

.ParseFiles(files...)

then I think that's what you're looking for. That way you can associate the FuncMap with the templates before parsing them.

Keyur Shah

unread,
Aug 7, 2013, 4:44:55 PM8/7/13
to golan...@googlegroups.com, Keyur Shah
I tried both and neither worked.

Even after replacing Execute with ExecuteTemplate I get the same error: html/template: "anyname" is an incomplete template

DeedleFake - your example used text/template. If you change the import to html/template it throws a nil pointer:

Kyle Lemons

unread,
Aug 7, 2013, 6:57:40 PM8/7/13
to Keyur Shah, golang-nuts
On Wed, Aug 7, 2013 at 1:44 PM, Keyur Shah <key...@gmail.com> wrote:
I tried both and neither worked.

Even after replacing Execute with ExecuteTemplate I get the same error: html/template: "anyname" is an incomplete template

Did you have a file named "anyname"?  You have to ExecuteTemplate with the name of one of the files or the name of one of the templates within one of the files.

Keyur Shah

unread,
Aug 8, 2013, 12:47:08 PM8/8/13
to golan...@googlegroups.com, Keyur Shah
Thank you. Got it to work based on your suggestion.

BTW - it only worked with the name of the first file. Any other name and it didn't yield any output.

Here's the relevant working code snippet:

tname := filepath.Base(templatesFiles[0])
t, _ := template.New(tname).Funcs(f).ParseFiles(templateFiles...)
t.ExecuteTemplate(w, tname, data)

Thanks,
Keyur

Kyle Lemons

unread,
Aug 8, 2013, 1:37:43 PM8/8/13
to Keyur Shah, golang-nuts
Don't ignore your errors.

Keyur Shah

unread,
Aug 8, 2013, 1:47:48 PM8/8/13
to golan...@googlegroups.com, Keyur Shah
Of course I don't. I do in forum posts to reduce noise.

Kyle Lemons

unread,
Aug 8, 2013, 2:11:47 PM8/8/13
to Keyur Shah, golang-nuts
That makes it impossible for us to know that you are checking your errors, then.  If you get no output from a template invocation, it either means that there was nothing to write or you got an error before anything was written.
Reply all
Reply to author
Forward
0 new messages