golang/go

html/template: document ability to modify FuncMap after template parse by calling Funcs again

已关闭

#34,680 创建于 2019年10月3日

 (20 条评论) (2 个反应) (0 位负责人)Go (19,008 个派生)batch import
DocumentationNeedsFixhelp wanted

仓库指标

星标
 (133,883 个星标)
PR 合并指标
 (30 天内没有已合并 PR)

描述

Background

I have a bunch of templates that have a complex dependency structure like:

 A -> B, D, E
 B ->  E, F
 C -> E, G
 D -> F, H
 E -> H
 F -> nil
 G -> nil
 H -> nil

The contents of the corresponding files ('A.tmpl', 'B.tmpl', etc.) are static; however, the template.FuncMap that they reference contain implicit reference to captured state that varies by caller. That is, the FuncMap is created like so:

func createFuncMap(request *rpc.Request) {
   result := template.FuncMap {
     "Foo": createFooFunc(request),
     "Bar": createBarFunc(request),
      ...
   }
  return request
}

What I Want to Do

I'd like to be able to preparse all of the various files irrespective of the func map (or perhaps with a whitelist of functions that will be defined), and I'd like to parse the individual pieces separately (e.g. parse 'F' only once, even though it is a dependency of 'B' and 'D'), and then somehow combine the parsed templates together like:

   func getTemplate(name string) *template.Template {
     result := template.New(name).Funcs(getStubFunctionMap())
     for _, dep := range getDeps(name) {
        result.AddDep(getTemplate(dep))
      }
      result.Parse(getFileContent(name))
      return result
    }

I'd also like to trivially rebind the function map as in:

   func getBoundTemplate(name string, request *rpc.Request) *template.Template {
     cachedTemplate := getOrCreateCachedTemplate(name)
     boundTemplate := cachedTemplate.Clone().Funcs(funcMapFor(request))
     return boundTemplate
   }

Why I Can't Do It

The documentation of html/template makes it appear that parsing is context dependent and that parsing is linear (dependencies can be added linearly, but cannot be combined from multiple, already-parsed templates). This is a pretty major limitation of the interface.

Impact of This Limitation

This is a major efficiency problem; I want to parse a complex network of templates upfront before receiving requests and do very minimal work on each request. This structure is causing much more work to happen in the context of every request.

For more specifics of this use case, reach out to me directly from your @google.com account, and I can share more details of the specific code in question.

贡献者指南