Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

text/template: allow explicit redefinition of a template #11642

Closed
parkr opened this issue Jul 9, 2015 · 3 comments
Closed

text/template: allow explicit redefinition of a template #11642

parkr opened this issue Jul 9, 2015 · 3 comments

Comments

@parkr
Copy link

parkr commented Jul 9, 2015

Hey Go team,

I am interested in redefinition of templates. Implicit redefinition is disallowed. How about explicit redefinition? Either:

  • Template.Remove(name string) followed by Template.ParseFiles(names ...string)
  • Template.Redefine(name, body string) / Template.RedefineFile(name, file string)

Scenario

We have a server which watches a folder for updates. When it receives a write or create for a file, it re-reads in the template. This allows for no-downtime updates to our templates, which is something we value greatly. It also allows for a more streamlined development process (developer isn't spending time restarting the server locally on changes).

With each filesystem event, we receive the event type and the file it affects. We would like to be able to redefine this template at runtime as these events are triggered.

Currently...

// Template has been changes on the filesystem.
// Re-read and parse. Store the latest.
// Always throws the 'redefinition' error.
_, err := rootTmpl.ParseFiles(event.FileName)
if err != nil {
    log.Printf("error reading template '%s': %v", event.FileName, err)
}

Unfortunately, this fails every time, with template: redefinition of template %NAME%.

Proposal

My proposal is to allow an explicit removal or redefinition. An example with Template.Remove(name string)...

// Allow explicit removal of a template to allow redefinition.
err := rootTmpl.Remove(event.FileName)
if err != nil && err != template.ErrorNoSuchTemplate {
    log.Printf("error removing template '%s': %v", event.FileName, err)
}

// This should NOT return an error.
_, err = rootTmpl.ParseFiles(event.FileName)
if err != nil {
    log.Printf("error reading template '%s': %v", event.FileName, err)
}

Current Work-Around

To get around this, we bind to SIGUSR1 and re-read all the templates (Template.ParseFilesGlob), blocking requests until it's re-defined.

@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Jul 9, 2015
@parkr
Copy link
Author

parkr commented Sep 15, 2015

Are there any thoughts here? Am I barking up the wrong tree?

@adg
Copy link
Contributor

adg commented Sep 15, 2015

@robpike would an API like this allay your concerns about accidental template redefinition?

@robpike
Copy link
Contributor

robpike commented Sep 17, 2015

This is already doable without too much trouble by synchronously reparsing the full set of templates when one changes. Plus, removing a template like this will violate invariants maintained by html/template, which escapes the content based on a statically knowable set of templates.

@robpike robpike closed this as completed Sep 17, 2015
@golang golang locked and limited conversation to collaborators Sep 22, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants