Template set

281 views
Skip to first unread message

bsr

unread,
Dec 31, 2011, 10:23:25 PM12/31/11
to golang-nuts
Hello,
Should the template always have to have "define" clause? Why the
below code gives error

panic: template: set:2: expected left delim in define clause; got "I
am heade"...

thanks,
bsr.

------- main.go --------
package main

import (
"template"
"log"
"os"
)

var fnlist = []string{"header.set", "footer.set", "main.set"}

func main() {
//s, err := template.ParseSetGlob("*.set") --intentionally not using
in this example
set := &template.Set{}
for _, filename := range fnlist {
set = template.SetMust(set.ParseFiles(filename))
}
err := set.Execute(os.Stdout, "main", nil)
if err != nil {
log.Fatal("exec error:", err)
}

}

-------- end main.go -----
------ header.set -------
I am header ...
----end header.set -----
-----footer.set -----
... I am footer
---- end footer.set ----
---- main.set -----
{{template "header"}}
.. I am main ...
{{template "footer"}}

tux21b

unread,
Jan 1, 2012, 6:04:57 AM1/1/12
to golan...@googlegroups.com
On Sunday, January 1, 2012 4:23:25 AM UTC+1, bsr wrote:
  Should the template always have to have "define" clause?
Yes. If you want to parse files without {{define}}s, you have to use the ParseTemplateGlob() function instead.

Newer versions of the "text/template" API do not distinguish between Sets and Templates anymore.
The old "Template" type isn't exported anymore, and the "Set" type has been renamed to "Template".
Also, those functions for parsing Sets (e.g. ParseSetGlob) had been removed. ParseGlob() now
accepts both. So, the new API is a bit easier to use.

bsr

unread,
Jan 1, 2012, 9:56:36 AM1/1/12
to golang-nuts
I modified the program as shown below, keeping the template same.

panic: runtime error: invalid memory address or nil pointer
dereference
[signal 0xb code=0x1 addr=0x8 pc=0x25bbb]

goroutine 1 [running]:
html/template.(*Template).ExecuteTemplate(0x421ba1e0, 0x421c75d0,
0x421c8008, 0xededc, 0x6e69616d00000004, ...)
/Users/.../go/src/pkg/html/template/template.go:57 +0x99
main.main()
/Users/...tmpl/main.go:22 +0x1cb

1) What is wrong? Is it because data is nil?
2) I tried to track looking at the template source. (http://
weekly.golang.org/src/pkg/html/template/template.go)
Line 24 text *template.Template
There is a reason given why not embed text.Template.

// we need to keep our version of the name space and the underlying
// template's in sync.

when is it need to distinguish the namespace like this?

thanks and Happy NewYear,
bsr
------ main.go ------
package main

import (
"log"
"os"
"html/template"
)

func main() {
t, err := template.ParseFiles("header.set", "footer.set",
"main.set")
if err != nil {
log.Fatal("parse error:", err)
}

err = t.ExecuteTemplate(os.Stdout, "main", nil)
if err != nil {
log.Fatal("exec error:", err)
}

}

---- end main.go ---

bsr

unread,
Jan 1, 2012, 12:12:10 PM1/1/12
to golang-nuts
Btw, I use latest weekly now.

According to the doc, "ParseGlob is equivalent to calling
ParseFiles ..", so doesn't mention different kind of template syntax
(with/wo {define}). Anyway, I tried parseglob like,

t, err := template.ParseGlob("*.set")
...
err = t.ExecuteTemplate(os.Stdout, "main", nil)

but still the same

panic: runtime error: invalid memory address or nil pointer
dereference

When I change to use execute,

err = t.Execute(os.Stdout, nil)

it prints

... I am footer

It might have executed last/random from the template set.

I might have misinterpreted this statement "The returned template's
name will have the (base) name .."

When I use ParseFiles, I was expecting to get a set of templates named
by file name (base --> without path??). So, instead of naming it with
{define}, I can name it explicitly through my program


thanks,
bsr

bsr

unread,
Jan 1, 2012, 1:14:01 PM1/1/12
to golang-nuts
Sorry, I understand the naming now "The returned template's name will
have the (base) name and (parsed) contents of the first file. ". It
indeed created the template with the name of first file. So this code
worked.http://weekly.play.golang.org/p/xk0MDveOvn

But I had to use {define} in all the templates.

{{define "footer"}}... I am footer{{end}}
{{define "header"}}I am header ...{{end}}
{{template "header"}}
.. I am main ...
{{template "footer"}}

So, it appears {define} is mandatory., even with glob.

Another question

the below code works, but if I call,
err = t.ExecuteTemplate(os.Stdout, "root", nil)

it fails
panic: html/template internal error: template escaping out of sync

Does this mean, the user has to explicitly state where should the
template execution start? When is the name of template created with
"New" useful?

------------ pgm ----------

package main

import (
"os"
"html/template"
)

func main() {
t, err := template.New("root").ParseFiles("main.set", "footer.set",
"header.set")
if err != nil {
panic(err)
}

err = t.Execute(os.Stdout, nil)
err = t.ExecuteTemplate(os.Stdout, "main.set", nil)
if err != nil {
panic(err)

D Smithson

unread,
Jan 1, 2012, 2:11:49 PM1/1/12
to golan...@googlegroups.com
I've struggled with these same issues.  Here's what I do:

1) Create a dummy template and configure it as needed for parsing more templates.

t, err := template.New("dummy").Parse(`{{define "dummy"}}{{end}}`)
if err != nil { panic(err) }
t.Funcs(myFuncs)

2) Use t.ParseFiles, t.ParseGlob as needed.

3) Assume that {{define}} is mandatory.

This is something that I found that works, but it might not be necessary given recent changes to the code.  


bsr

unread,
Jan 1, 2012, 3:14:03 PM1/1/12
to golang-nuts
D Thank you so much for your response. I am trying to port code from
"old" template to new one. I appreciate the effort to develop and
usefulness of new template package.
The old template didn't force any tag to use template and even pure
html/js worked, that's y I am bit persistent.
Hope to get more response from the authors after holidays.
Thanks again,
bsr.
Reply all
Reply to author
Forward
0 new messages