]> Cypherpunks repositories - gostls13.git/commitdiff
internal/lazytemplate: add a lazy template wrapper
authorDaniel Martí <mvdan@mvdan.cc>
Wed, 27 Feb 2019 22:02:51 +0000 (22:02 +0000)
committerDaniel Martí <mvdan@mvdan.cc>
Wed, 27 Feb 2019 23:49:01 +0000 (23:49 +0000)
Similar to internal/lazyregexp, this will allow removing unnecessary
work from init functions with trivial refactors, thanks to sync.Once.

Copy the structure. The only major difference is that a template also
carries a name.

For #29382.

Change-Id: I65d096dc2e2072b310bf59a814cd62669856b5b5
Reviewed-on: https://go-review.googlesource.com/c/164337
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/go/build/deps_test.go
src/internal/lazyregexp/lazyre.go
src/internal/lazytemplate/lazytemplate.go [new file with mode: 0644]

index 3b6dbd62219b84a4c9dff5e1370f3a13944c2f21..8e289ae95d3ecc0967ac839b87090e365954fcd7 100644 (file)
@@ -194,11 +194,12 @@ var pkgDeps = map[string][]string{
        "runtime/trace":  {"L0", "context", "fmt"},
        "text/tabwriter": {"L2"},
 
-       "testing":             {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
-       "testing/iotest":      {"L2", "log"},
-       "testing/quick":       {"L2", "flag", "fmt", "reflect", "time"},
-       "internal/testenv":    {"L2", "OS", "flag", "testing", "syscall"},
-       "internal/lazyregexp": {"L2", "OS", "regexp"},
+       "testing":               {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
+       "testing/iotest":        {"L2", "log"},
+       "testing/quick":         {"L2", "flag", "fmt", "reflect", "time"},
+       "internal/testenv":      {"L2", "OS", "flag", "testing", "syscall"},
+       "internal/lazyregexp":   {"L2", "OS", "regexp"},
+       "internal/lazytemplate": {"L2", "OS", "text/template"},
 
        // L4 is defined as L3+fmt+log+time, because in general once
        // you're using L3 packages, use of fmt, log, or time is not a big deal.
index 0c744fa39f8d4ec78813c522d532c0675f82505a..2681af35af1954b1384eecc12bcea655462a8776 100644 (file)
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// Package lazyregexp is a thin wrapper over regexp, allowing the use of global
+// regexp variables without forcing them to be compiled at init.
 package lazyregexp
 
 import (
@@ -11,6 +13,8 @@ import (
        "sync"
 )
 
+// Regexp is a wrapper around regexp.Regexp, where the underlying regexp will be
+// compiled the first time it is needed.
 type Regexp struct {
        str  string
        once sync.Once
@@ -61,6 +65,9 @@ func (r *Regexp) SubexpNames() []string {
 
 var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
 
+// New creates a new lazy regexp, delaying the compiling work until it is first
+// needed. If the code is being run as part of tests, the regexp compiling will
+// happen immediately.
 func New(str string) *Regexp {
        lr := &Regexp{str: str}
        if inTest {
diff --git a/src/internal/lazytemplate/lazytemplate.go b/src/internal/lazytemplate/lazytemplate.go
new file mode 100644 (file)
index 0000000..c83eaea
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2019 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 lazytemplate is a thin wrapper over text/template, allowing the use
+// of global template variables without forcing them to be parsed at init.
+package lazytemplate
+
+import (
+       "io"
+       "os"
+       "strings"
+       "sync"
+       "text/template"
+)
+
+// Template is a wrapper around text/template.Template, where the underlying
+// template will be parsed the first time it is needed.
+type Template struct {
+       name, text string
+
+       once sync.Once
+       tmpl *template.Template
+}
+
+func (r *Template) tp() *template.Template {
+       r.once.Do(r.build)
+       return r.tmpl
+}
+
+func (r *Template) build() {
+       r.tmpl = template.Must(template.New(r.name).Parse(r.text))
+       r.name, r.text = "", ""
+}
+
+func (r *Template) Execute(w io.Writer, data interface{}) error {
+       return r.tp().Execute(w, data)
+}
+
+var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
+
+// New creates a new lazy template, delaying the parsing work until it is first
+// needed. If the code is being run as part of tests, the template parsing will
+// happen immediately.
+func New(name, text string) *Template {
+       lt := &Template{name: name, text: text}
+       if inTest {
+               // In tests, always parse the templates early.
+               lt.tp()
+       }
+       return lt
+}