提案详情
Rangefunc 更改是为了在自定义函数上添加对范围的支持。
text/html 模板标准库有一个范围操作符,其功能如 documented 所示。
模板库应该支持对函数的范围遍历。使用场景是希望在 SQL 行迭代器上返回一个 Rangefunc,然后将其传递给模板进行文本生成。
这是我们在 https://groups.google.com/g/golang-nuts/c/_lykyoQHmGc 小组中的讨论内容。
提案详情
Rangefunc 更改是为了在自定义函数上添加对范围的支持。
text/html 模板标准库有一个范围操作符,其功能如 documented 所示。
模板库应该支持对函数的范围遍历。使用场景是希望在 SQL 行迭代器上返回一个 Rangefunc,然后将其传递给模板进行文本生成。
这是我们在 https://groups.google.com/g/golang-nuts/c/_lykyoQHmGc 小组中的讨论内容。
8条答案
按热度按时间vnzz0bqm1#
我认为我们需要定义一些语义,并且我认为可能存在一些未明确回答的问题。
首先,显然,有一对一变量和二元变量的迭代器。在
{{ range $x }}
中,如果$x
是iter.Seq2[A, B]
,应该将map[K]V
设置为什么值?为了一致性,我们将其设置为 值,这意味着它应该是B
。另一方面,没有先验保证iter.Seq2
的第二个参数确实一定是“类似值”的。然后我们有
range
形式{{ range $x, $y := $z }}
,即一个初始化一个或两个变量的range
动作。可以假设使用两个变量与iter.Seq
一起将是一个错误。使用一个变量与iter.Seq2
(参见 also #65236)是否也应该是一个错误?最后:如果在模板中调用函数或方法(无论是通过使用函数名作为操作,还是使用
call
函数),该函数可以选择返回类型为error
的第二个参数:如果那个error
不是nil
,则中止模板执行并返回错误。这引发了如何处理iter.Seq2[T, error]
的问题。据我所知,关于迭代器的错误处理并不是完全清楚的。例如,如果你有一个从文件中读取行的迭代器,将每行解析为结构体,它可能会有两种失败方式:1.
Read
可以失败,致命地中止迭代;2. 对单行的解析失败,允许以不同的方式处理该行的错误,但继续迭代。有些人建议对两者都使用iter.Seq2[T, error]
,在这种情况下,范围遍历它的模板操作应该在发生错误时中止。另一方面,也许合理的做法是仍然从模板中处理该错误并继续迭代 - 只在“致命”错误上中止。我现在不确定我们在这一点上想要做出多少策略选择。我可以想象的一种替代方案是说你可以以三种方式遍历
iter.Seq2
:1.{{ range $it }}
,它产生T
并中止模板执行,如果第二个参数是错误;2.{{ range $x := $it }}
,它的行为相同(但设置$x
而不是.
)和3.{{ range $x, $err := $it }}
,它在错误上不中止,允许模板随心所欲地处理它。这实际上将控制权交给了模板作者。如果我们采纳这个建议,我们可能希望使
{{ range $it }}
/{{ range $x := $it }}
在应用于iter.Seq2[A, B]
时产生A
- 这与Map不一致,但与iter.Seq2[T, error]
更一致。至少这是我的想法。可能还有其他定义这些语义的方法。
9rygscc12#
关于语义,似乎我们应该要求如果迭代器产生2个值,那么你必须使用{{range $x, $y := $f}}形式。
dluptydi3#
此建议已添加到建议项目中的活动列,并将在每周的建议审查会议上进行审查。
— rsc 建议审查组
uubf1zoe4#
允许对int进行遍历也是一致的。
5n0oy7gb5#
这看起来没问题,但我们应该等待 #66056 来帮助实施。
fcg9iug36#
根据以上讨论,这个提案看起来像是很有可能被接受。
— rsc(提案审查组)
该提案是允许在Go中对func和int进行范围遍历。
yb3bgrhw7#
共识没有变化,所以接受。🎉
这个问题现在跟踪实施提案的工作。
— rsc提案审查组
提案是允许在Go中与func和int一样对范围进行操作。
vi4fp9gy8#
https://go.dev/cl/596956提到了这个问题:
text/template: support range-over-func