diff --git a/src/html/template/content.go b/src/html/template/content.go
index 4aadf64df252f..6ba87a955035a 100644
--- a/src/html/template/content.go
+++ b/src/html/template/content.go
@@ -169,8 +169,17 @@ func stringify(args ...interface{}) (string, contentType) {
return string(s), contentTypeSrcset
}
}
- for i, arg := range args {
+ i := 0
+ for _, arg := range args {
+ // We skip untyped nil arguments for backward compatibility.
+ // Without this they would be output as , escaped.
+ // See issue 25875.
+ if arg == nil {
+ continue
+ }
+
args[i] = indirectToStringerOrError(arg)
+ i++
}
- return fmt.Sprint(args...), contentTypePlain
+ return fmt.Sprint(args[:i]...), contentTypePlain
}
diff --git a/src/html/template/content_test.go b/src/html/template/content_test.go
index cc092f50c0c1e..72d56f50c1441 100644
--- a/src/html/template/content_test.go
+++ b/src/html/template/content_test.go
@@ -447,10 +447,9 @@ func TestEscapingNilNonemptyInterfaces(t *testing.T) {
testData := struct{ E error }{} // any non-empty interface here will do; error is just ready at hand
tmpl.Execute(got, testData)
- // Use this data instead of just hard-coding "<nil>" to avoid
- // dependencies on the html escaper and the behavior of fmt w.r.t. nil.
+ // A non-empty interface should print like an empty interface.
want := new(bytes.Buffer)
- data := struct{ E string }{E: fmt.Sprint(nil)}
+ data := struct{ E interface{} }{}
tmpl.Execute(want, data)
if !bytes.Equal(want.Bytes(), got.Bytes()) {
diff --git a/src/html/template/doc.go b/src/html/template/doc.go
index 35d171c3fca2d..290ec81b9672a 100644
--- a/src/html/template/doc.go
+++ b/src/html/template/doc.go
@@ -70,6 +70,9 @@ In this case it becomes
where urlescaper, attrescaper, and htmlescaper are aliases for internal escaping
functions.
+For these internal escaping functions, if an action pipeline evaluates to
+a nil interface value, it is treated as though it were an empty string.
+
Errors
See the documentation of ErrorCode for details.
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
index d5c258ecaa87d..e6c12a8a254b2 100644
--- a/src/html/template/escape_test.go
+++ b/src/html/template/escape_test.go
@@ -35,7 +35,8 @@ func TestEscape(t *testing.T) {
A, E []string
B, M json.Marshaler
N int
- Z *int
+ U interface{} // untyped nil
+ Z *int // typed nil
W HTML
}{
F: false,
@@ -48,6 +49,7 @@ func TestEscape(t *testing.T) {
N: 42,
B: &badMarshaler{},
M: &goodMarshaler{},
+ U: nil,
Z: nil,
W: HTML(`¡Hello, !`),
}
@@ -113,6 +115,16 @@ func TestEscape(t *testing.T) {
"{{.T}}",
"true",
},
+ {
+ "untypedNilValue",
+ "{{.U}}",
+ "",
+ },
+ {
+ "typedNilValue",
+ "{{.Z}}",
+ "<nil>",
+ },
{
"constant",
``,
@@ -199,10 +211,15 @@ func TestEscape(t *testing.T) {
`