golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.02k stars 17.68k forks source link

text/template: unclear about pipelines as arguments #61029

Open juriad opened 1 year ago

juriad commented 1 year ago

What is the URL of the page with the issue?

https://pkg.go.dev/text/template#hdr-Pipelines

I came here from https://stackoverflow.com/questions/59795596/how-to-make-nested-variables-optional-in-helm

What did you expect to see?

The documentation should change the definition of a Parenthesized Argument to refer to Pipeline instead. It should also describe what happens with the value when it is nil. Similar explanation is missing for Variables.

The reader should be able to understand why the following works and how it derives from the grammar.

{{ $x := .abc }}
{{ $x = $x.def }}
{{ $x = $x.ghi }}
{{ $x }}

{{ ((.abc).def).ghi }}

{{ $y := ((.abc).def) }}
{{ $y.ghi }}

and why {{ .abc.def.ghi }} does not work. This example shows that a Parenthesized Arguments work similarly to Variables.

The description of If Action defines what empty means for the other Actions and Functions. The definition of empty deserves a better place.

What did you see instead?

The documentation of Arguments, Commands and Pipelines is vague up to the point of being incorrect. It requires a lot of imagination to figure out that a Pipeline can be used as an Argument. It is hinted by the examples:

A parenthesized instance of one the above, for grouping. The result may be accessed by a field or map key invocation. print (.F1 arg1) (.F2 arg2) (.StructValuedMethod "arg").Field

Clearly .F1 arg1 is neither of the "above". It looks like a Method Call which is defined later under Command. The other example is:

{{printf "%q" (print "out" "put")}} A parenthesized argument.

where the parentheses enclose a Function Call (which is a Command and not an Argument).

The SO reply author quotes

If the value of the pipeline is empty, no output is generated... The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero.

for the reason why the parentheses turn an empty value into no output which is then chained. This behavior is mentioned only within If Action and With Action, where I believe it describes the consequence of T1 not being executed.

ianlancetaylor commented 1 year ago

CC @robpike