Source File
template.go
Belonging Package
text/template
// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package templateimport ()// common holds the information shared by related templates.type common struct {tmpl map[string]*Template // Map from name to defined templates.muTmpl sync.RWMutex // protects tmploption option// We use two maps, one for parsing and one for execution.// This separation makes the API cleaner since it doesn't// expose reflection to the client.muFuncs sync.RWMutex // protects parseFuncs and execFuncsparseFuncs FuncMapexecFuncs map[string]reflect.Value}// Template is the representation of a parsed template. The *parse.Tree// field is exported only for use by [html/template] and should be treated// as unexported by all other clients.type Template struct {name string*parse.Tree*commonleftDelim stringrightDelim string}// New allocates a new, undefined template with the given name.func ( string) *Template {:= &Template{name: ,}.init()return}// Name returns the name of the template.func ( *Template) () string {return .name}// New allocates a new, undefined template associated with the given one and with the same// delimiters. The association, which is transitive, allows one template to// invoke another with a {{template}} action.//// Because associated templates share underlying data, template construction// cannot be done safely in parallel. Once the templates are constructed, they// can be executed in parallel.func ( *Template) ( string) *Template {.init():= &Template{name: ,common: .common,leftDelim: .leftDelim,rightDelim: .rightDelim,}return}// init guarantees that t has a valid common structure.func ( *Template) () {if .common == nil {:= new(common).tmpl = make(map[string]*Template).parseFuncs = make(FuncMap).execFuncs = make(map[string]reflect.Value).common =}}// Clone returns a duplicate of the template, including all associated// templates. The actual representation is not copied, but the name space of// associated templates is, so further calls to [Template.Parse] in the copy will add// templates to the copy but not to the original. Clone can be used to prepare// common templates and use them with variant definitions for other templates// by adding the variants after the clone is made.func ( *Template) () (*Template, error) {:= .copy(nil).init()if .common == nil {return , nil}.option = .option.muTmpl.RLock()defer .muTmpl.RUnlock()for , := range .tmpl {if == .name {.tmpl[.name] =continue}// The associated templates share nt's common structure.:= .copy(.common).tmpl[] =}.muFuncs.RLock()defer .muFuncs.RUnlock()maps.Copy(.parseFuncs, .parseFuncs)maps.Copy(.execFuncs, .execFuncs)return , nil}// copy returns a shallow copy of t, with common set to the argument.func ( *Template) ( *common) *Template {return &Template{name: .name,Tree: .Tree,common: ,leftDelim: .leftDelim,rightDelim: .rightDelim,}}// AddParseTree associates the argument parse tree with the template t, giving// it the specified name. If the template has not been defined, this tree becomes// its definition. If it has been defined and already has that name, the existing// definition is replaced; otherwise a new template is created, defined, and returned.func ( *Template) ( string, *parse.Tree) (*Template, error) {.init().muTmpl.Lock()defer .muTmpl.Unlock():=if != .name {= .New()}// Even if nt == t, we need to install it in the common.tmpl map.if .associate(, ) || .Tree == nil {.Tree =}return , nil}// Templates returns a slice of defined templates associated with t.func ( *Template) () []*Template {if .common == nil {return nil}// Return a slice so we don't expose the map..muTmpl.RLock()defer .muTmpl.RUnlock():= make([]*Template, 0, len(.tmpl))for , := range .tmpl {= append(, )}return}// Delims sets the action delimiters to the specified strings, to be used in// subsequent calls to [Template.Parse], [Template.ParseFiles], or [Template.ParseGlob]. Nested template// definitions will inherit the settings. An empty delimiter stands for the// corresponding default: {{ or }}.// The return value is the template, so calls can be chained.func ( *Template) (, string) *Template {.init().leftDelim =.rightDelim =return}// Funcs adds the elements of the argument map to the template's function map.// It must be called before the template is parsed.// It panics if a value in the map is not a function with appropriate return// type or if the name cannot be used syntactically as a function in a template.// It is legal to overwrite elements of the map. The return value is the template,// so calls can be chained.func ( *Template) ( FuncMap) *Template {.init().muFuncs.Lock()defer .muFuncs.Unlock()addValueFuncs(.execFuncs, )addFuncs(.parseFuncs, )return}// Lookup returns the template with the given name that is associated with t.// It returns nil if there is no such template or the template has no definition.func ( *Template) ( string) *Template {if .common == nil {return nil}.muTmpl.RLock()defer .muTmpl.RUnlock()return .tmpl[]}// Parse parses text as a template body for t.// Named template definitions ({{define ...}} or {{block ...}} statements) in text// define additional templates associated with t and are removed from the// definition of t itself.//// Templates can be redefined in successive calls to Parse.// A template definition with a body containing only white space and comments// is considered empty and will not replace an existing template's body.// This allows using Parse to add new named template definitions without// overwriting the main template body.func ( *Template) ( string) (*Template, error) {.init().muFuncs.RLock(), := parse.Parse(.name, , .leftDelim, .rightDelim, .parseFuncs, builtins()).muFuncs.RUnlock()if != nil {return nil,}// Add the newly parsed trees, including the one for t, into our common structure.for , := range {if , := .AddParseTree(, ); != nil {return nil,}}return , nil}// associate installs the new template into the group of templates associated// with t. The two are already known to share the common structure.// The boolean return value reports whether to store this tree as t.Tree.func ( *Template) ( *Template, *parse.Tree) bool {if .common != .common {panic("internal error: associate not common")}if := .tmpl[.name]; != nil && parse.IsEmptyTree(.Root) && .Tree != nil {// If a template by that name exists,// don't replace it with an empty template.return false}.tmpl[.name] =return true}
![]() |
The pages are generated with Golds v0.7.9-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |