-
Notifications
You must be signed in to change notification settings - Fork 18k
text/template: Inconsistent handling off nil values in if and with #30481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Note that |
“empty” in the context of “If the value of the pipeline is empty” means “equal to the zero value of its type”. At the core, this is another instance of https://golang.org/doc/faq#nil_error, and |
@bcmills I can sympathize with your urge to be effective and close this issue. But this is a real issue that need some kind of action, even if just a documentation update. In general, I think every person who uses the Go template API expect this to not panic with a nilpointer, if at all possible:
Even after carefully reading the documentation, I think most people would expect the above to not crash. And note that this is less obvious and much harder to debug in a dynamic template context. All of my 4 examples (even if there are duplicates) would be considered empty by most people. There is nothing here that talks about "empty" (or even zero values), so that is, I guess, a vague sentence that could be interprited to mean just about anything. |
I'm sure I'm talking to myself here, but if you expand the program above: package main
import (
"bytes"
"fmt"
"log"
"text/template"
)
type Niller interface {
Nil() Niller
Foo() string
}
type Nill struct {
nilv Niller
}
func (n Nill) Nil() Niller {
return n.nilv
}
func (n Nill) Foo() string {
return "asdf"
}
func main() {
tmpl, err := template.New("").Parse(`{{ with .Nil }}Failed, got {{ . }}{{ else }}OK{{ end }}`)
if err != nil {
log.Fatal(err)
}
var (
nil1 Niller = (*Nill)(nil)
nil2 Niller
nil3 *Nill
nil4 Niller = nil
)
for i, niller := range []Niller{nil1, nil2, nil3, nil4} {
var buff bytes.Buffer
n := &Nill{nilv: niller}
a, b := template.IsTrue(n.Nil())
err = tmpl.Execute(&buff, n)
if err != nil {
fmt.Println("error:", err)
continue
}
fmt.Println(i+1, a, b, buff.String())
}
} You get: 1 false true Failed, got <nil>
2 false true OK
3 false true Failed, got <nil>
4 false true OK I have looked at the code, and I fail to understand it. |
I did follow this thread yesterday, but I had work and a meetup to speak at, so I didn't have a chance to respond properly :) I see you've opened a new issue, so I'll just focus on that one. |
The above prints:
This issue makes more sense if you also glance at these:
if
andwhere
.template.IsTrue
The documentation for both
if
andwith
is similar:I'm not sure what the definition of "empty" in the above, but as all of the above cases outputs
<nil>
, I assume it is the truthines defined intemplate.IsTrue
that is used.The text was updated successfully, but these errors were encountered: