Commit 1acff5fe authored by Dieter Plaetinck's avatar Dieter Plaetinck Committed by Rob Pike

template: warn about interleaved nature of writes

Execute incurs separate writes for each "step", e.g. each
variable that needs to be printed, and the final newline.
While it is correct to state that templates can be executed
concurrently, there is a more subtle nuance that is easily missed:
when writing to the same writer, the writes from concurrent execute
calls can be interleaved, leading to unexpected output.

Change-Id: I0abbd7960d8a8d15e109a8a3eeff3b43b852bbbf
Reviewed-on: https://go-review.googlesource.com/37444Reviewed-by: 's avatarRob Pike <r@golang.org>
parent 27a10f7d
......@@ -112,7 +112,8 @@ func (t *Template) escape() error {
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel.
// A template may be executed safely in parallel, although if parallel
// executions share a Writer the output may be interleaved.
func (t *Template) Execute(wr io.Writer, data interface{}) error {
if err := t.escape(); err != nil {
return err
......@@ -125,7 +126,8 @@ func (t *Template) Execute(wr io.Writer, data interface{}) error {
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel.
// A template may be executed safely in parallel, although if parallel
// executions share a Writer the output may be interleaved.
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
tmpl, err := t.lookupAndEscapeTemplate(name)
if err != nil {
......
......@@ -20,7 +20,8 @@ The input text for a template is UTF-8-encoded text in any format.
"{{" and "}}"; all text outside actions is copied to the output unchanged.
Except for raw strings, actions may not span newlines, although comments can.
Once parsed, a template may be executed safely in parallel.
Once parsed, a template may be executed safely in parallel, although if parallel
executions share a Writer the output may be interleaved.
Here is a trivial example that prints "17 items are made of wool".
......
......@@ -153,7 +153,8 @@ func errRecover(errp *error) {
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel.
// A template may be executed safely in parallel, although if parallel
// executions share a Writer the output may be interleaved.
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
var tmpl *Template
if t.common != nil {
......@@ -170,7 +171,8 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{})
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel.
// A template may be executed safely in parallel, although if parallel
// executions share a Writer the output may be interleaved.
//
// If data is a reflect.Value, the template applies to the concrete
// value that the reflect.Value holds, as in fmt.Print.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment