Skip to content

text/template: Inconsistent handling off nil values in if and with #30481

Closed
@bep

Description

@bep
package main

import (
	"bytes"
	"fmt"
	"log"
	"text/template"
)

type Niller interface {
	Nil() Niller
}

type Nill struct {
	nilv Niller
}

func (n Nill) Nil() Niller {
	return n.nilv
}

func main() {

	tmpl, err := template.New("").Parse(`{{ .Nil }}: {{ 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
		err = tmpl.Execute(&buff, &Nill{nilv: niller})
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(i+1, buff.String())
	}
}

The above prints:

1 <nil>: Failed, got <nil>
2 <nil>: OK
3 <nil>: Failed, got <nil>
4 <nil>: OK

This issue makes more sense if you also glance at these:

The documentation for both if and with is similar:

"If the value of the pipeline is empty, no output is generated"

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 in template.IsTrue that is used.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions