Home > Blockchain >  Why when I ignore the template.New() the program can run successfully?
Why when I ignore the template.New() the program can run successfully?

Time:10-07

I am trying to use html/template to parse a JSON in struct format.

func handler(w http.ResponseWriter, r *http.Request) {
    var issueList = template.Must(template.New("template01").ParseFiles("template01.tmpl"))
    result, err := SearchIssues(os.Args[1:])
    if err != nil {
        log.Fatal(err)
    }
    if err := issueList.Execute(w, result); err != nil {
        log.Fatal(err)
    }
}

The function SearchIssues is used to convert the stream into JSON format, it works well.

Then I try to parse the JSON by html/template using

var issueList = template.Must(template.New("template01").ParseFiles("template01.tmpl"))

When I access local services, there is an error : XXX is an incomplete or empty template.

But when I delete New("template01"). the program runs well.

Like this:

func handler(w http.ResponseWriter, r *http.Request) {
    var issueList = template.Must(template.ParseFiles("template01.tmpl"))
    result, err := SearchIssues(os.Args[1:])
    if err != nil {
        log.Fatal(err)
    }
    if err := issueList.Execute(w, result); err != nil {
        log.Fatal(err)
    }
}

I am not native speaker, English is not very well, sorry.

CodePudding user response:

The problem with your first code is that when you do:

var issueList = template.Must(template.New("template01").
    ParseFiles("template01.tmpl"))

template.New() will create a new template having the name "template01". The variable issueList will refer to this empty template. You call its Template.ParseFiles() method, which will parse the "template01.tmpl" file and create an associated template named "template01.tmpl". The variable issueList will still refer to the template01 template, not the one parsed from the file. When you call Template.Excute(), it executes the (default) template issueList designates, which is the empty template01. That's why you get the error incomplete or empty template.

In your second version:

var issueList = template.Must(template.ParseFiles("template01.tmpl"))

You call the template.ParseFiles() function, which parses the "template01.tmpl" file, and returns its template. So issueList will refer to the parsed template from the file, and not an empty template. So Template.Execute() will execute this template.

Note: if in the first case you'd use Template.ExecuteTemplate(), you can name the template you want to execute:

if err := issueList.Execute(w, "template01.tmpl", result); err != nil {
    log.Fatal(err)
}

This will succeed because you tell explicitly to execute the "template01.tmpl" parsed from the file, and not the default, empty template.

Also note that you should not parse the templates in your handler, it's slow. Parse it before that once, store the result in package level variables and just execute it in the handler. For dteails, see It takes too much time when using "template" package to generate a dynamic web page to client in Golang

For details about associated templates, see Go template name.

Also please use encoding/json to generate JSON output and not text/template or html/template. The template engine knows nothing about JSON format and encoding, and may easily generate invalid JSON.

  • Related