|
@@ -49,6 +49,9 @@ func ExecuteFunc(template, startTag, endTag string, w io.Writer, f TagFunc) (int
|
|
|
|
|
|
|
|
ni, err = f(w, unsafeBytes2String(s[:n]))
|
|
ni, err = f(w, unsafeBytes2String(s[:n]))
|
|
|
nn += int64(ni)
|
|
nn += int64(ni)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nn, err
|
|
|
|
|
+ }
|
|
|
s = s[n+len(b):]
|
|
s = s[n+len(b):]
|
|
|
}
|
|
}
|
|
|
ni, err = w.Write(s)
|
|
ni, err = w.Write(s)
|
|
@@ -81,19 +84,32 @@ func Execute(template, startTag, endTag string, w io.Writer, m map[string]interf
|
|
|
// This function is optimized for constantly changing templates.
|
|
// This function is optimized for constantly changing templates.
|
|
|
// Use Template.ExecuteFuncString for frozen templates.
|
|
// Use Template.ExecuteFuncString for frozen templates.
|
|
|
func ExecuteFuncString(template, startTag, endTag string, f TagFunc) string {
|
|
func ExecuteFuncString(template, startTag, endTag string, f TagFunc) string {
|
|
|
|
|
+ s, err := ExecuteFuncStringWithErr(template, startTag, endTag, f)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ panic(fmt.Sprintf("unexpected error: %s", err))
|
|
|
|
|
+ }
|
|
|
|
|
+ return s
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ExecuteFuncStringWithErr is nearly the same as ExecuteFuncString
|
|
|
|
|
+// but when f returns an error, ExecuteFuncStringWithErr won't panic like ExecuteFuncString
|
|
|
|
|
+// it just returns an empty string and the error f returned
|
|
|
|
|
+func ExecuteFuncStringWithErr(template, startTag, endTag string, f TagFunc) (string, error) {
|
|
|
tagsCount := bytes.Count(unsafeString2Bytes(template), unsafeString2Bytes(startTag))
|
|
tagsCount := bytes.Count(unsafeString2Bytes(template), unsafeString2Bytes(startTag))
|
|
|
if tagsCount == 0 {
|
|
if tagsCount == 0 {
|
|
|
- return template
|
|
|
|
|
|
|
+ return template, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bb := byteBufferPool.Get()
|
|
bb := byteBufferPool.Get()
|
|
|
if _, err := ExecuteFunc(template, startTag, endTag, bb, f); err != nil {
|
|
if _, err := ExecuteFunc(template, startTag, endTag, bb, f); err != nil {
|
|
|
- panic(fmt.Sprintf("unexpected error: %s", err))
|
|
|
|
|
|
|
+ bb.Reset()
|
|
|
|
|
+ byteBufferPool.Put(bb)
|
|
|
|
|
+ return "", err
|
|
|
}
|
|
}
|
|
|
s := string(bb.B)
|
|
s := string(bb.B)
|
|
|
bb.Reset()
|
|
bb.Reset()
|
|
|
byteBufferPool.Put(bb)
|
|
byteBufferPool.Put(bb)
|
|
|
- return s
|
|
|
|
|
|
|
+ return s, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var byteBufferPool bytebufferpool.Pool
|
|
var byteBufferPool bytebufferpool.Pool
|
|
@@ -275,14 +291,31 @@ func (t *Template) Execute(w io.Writer, m map[string]interface{}) (int64, error)
|
|
|
// This function is optimized for frozen templates.
|
|
// This function is optimized for frozen templates.
|
|
|
// Use ExecuteFuncString for constantly changing templates.
|
|
// Use ExecuteFuncString for constantly changing templates.
|
|
|
func (t *Template) ExecuteFuncString(f TagFunc) string {
|
|
func (t *Template) ExecuteFuncString(f TagFunc) string {
|
|
|
|
|
+ s, err := t.ExecuteFuncStringWithErr(f)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ panic(fmt.Sprintf("unexpected error: %s", err))
|
|
|
|
|
+ }
|
|
|
|
|
+ return s
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ExecuteFuncStringWithErr calls f on each template tag (placeholder) occurrence
|
|
|
|
|
+// and substitutes it with the data written to TagFunc's w.
|
|
|
|
|
+//
|
|
|
|
|
+// Returns the resulting string.
|
|
|
|
|
+//
|
|
|
|
|
+// This function is optimized for frozen templates.
|
|
|
|
|
+// Use ExecuteFuncString for constantly changing templates.
|
|
|
|
|
+func (t *Template) ExecuteFuncStringWithErr(f TagFunc) (string, error) {
|
|
|
bb := t.byteBufferPool.Get()
|
|
bb := t.byteBufferPool.Get()
|
|
|
if _, err := t.ExecuteFunc(bb, f); err != nil {
|
|
if _, err := t.ExecuteFunc(bb, f); err != nil {
|
|
|
- panic(fmt.Sprintf("unexpected error: %s", err))
|
|
|
|
|
|
|
+ bb.Reset()
|
|
|
|
|
+ t.byteBufferPool.Put(bb)
|
|
|
|
|
+ return "", err
|
|
|
}
|
|
}
|
|
|
s := string(bb.Bytes())
|
|
s := string(bb.Bytes())
|
|
|
bb.Reset()
|
|
bb.Reset()
|
|
|
t.byteBufferPool.Put(bb)
|
|
t.byteBufferPool.Put(bb)
|
|
|
- return s
|
|
|
|
|
|
|
+ return s, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ExecuteString substitutes template tags (placeholders) with the corresponding
|
|
// ExecuteString substitutes template tags (placeholders) with the corresponding
|