-
Notifications
You must be signed in to change notification settings - Fork 18k
text/template: add "return" action #53015
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
This proposal has been added to the active column of the proposals project |
@josharian Do you know whether this is a trivial change? |
No idea. I suspect that it is (return a sentinel error, handle the sentinel error), but I haven't tried it. Should I? |
DO NOT SUBMIT This is a quick and dirty experiment to see how hard it is to implement a return keyword for golang#53015.
It appears to be trivial, although I have no history with text/template, so my approach might be unwelcome. I cobbled together josharian@2a1e6f1 with a minimum of effort. (It obviously needs docs and probably more tests.) |
That looks entirely reasonable. I put the panics in for break and continue; using them for return too seems OK. /cc @robpike for any thoughts about whether we want to add 'return'. |
Should it return an error? Should it optionally return an error? Never having wanted this facility, I have no experience to lean on regarding how it should behave. |
It's fairly trivial to write a FuncMap entry that returns an error (see OP). And I'm not sure where the error would come from: In the typical case, errors come from FuncMaps that you call, and they already interrupt control flow. So the error would have to be passed in via Execute (weird), or we'd have to accept any type of thing as an error and then passed to fmt.Sprint and then errors.New. I am not opposed to an optional error, but I definitely wouldn't want to make it required. |
On further thought, I don’t think it should accept an error, as that would create an expectation that the calling template would also exit. But the property that is difficult to achieve with a FuncMap is precisely that nested templates returning early do not impact calling templates. |
In general templates don't return values, so plain return alone seems like it makes the most sense: it's like break/continue just for the overall current template "call" and not the enclosing loop. |
Given that templates don’t return values, would “exit” be clearer? |
Neither do some functions. :) I chose "return" because it matches the language, just like if, else, break, and so on. The one exception to that list is range, and it still trips me up every time I use it. |
Based on the discussion above, this proposal seems like a likely accept. |
I'm not sure what is actually being proposed. The conversation has drifted a bit. Can someone please clarify? Is it really just exit early from the current template invocation, and continue execution? If so, is there also need for an "exit", which was also suggested here? What is the actual problem being solved? Why is it important to stop execution early? I've literally never wanted that. |
Yes.
I don't think so. "exit" can be easily implemented using a FuncMap; "return" cannot. This is laid out in detail in the original proposal.
I have a lot of templates of the form:
I would like to be able to remove the layer of (virtual) indentation and write (as I would in code):
|
No change in consensus, so accepted. 🎉 |
Change https://go.dev/cl/425875 mentions this issue: |
There is currently no good way to cleanly stop template execution early.
I propose that we add a
return
action that stops execution of the current template, without error. When using nested templates, the calling template should keep executing. That is,return
should be scoped to the current template.This can be partially implemented with a simple FuncMap entry and a (custom) sentinel error:
The Go code executing the template can then recognize
ErrStop
and ignore it. However, this implementation stops the entire template execution, including caller (parent) templates. One can write an alternative FuncMap implementation of thetemplate
action that handles ErrStop. But that's a lot of machinery, and you must buffer the intermediate template result.The other alternative is to wrap large chunks of templates with
if
blocks, which is bad for readability.Given that Go style encourages early exits, the template package ought to support it.
cc @robpike @mvdan
The text was updated successfully, but these errors were encountered: