在 Go 模板范围循环中,循环外声明的变量是否在每次迭代时重置? [英] In a Go template range loop, are variables declared outside the loop reset on each iteration?

查看:33
本文介绍了在 Go 模板范围循环中,循环外声明的变量是否在每次迭代时重置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用在 Go 模板范围循环之外声明的变量来查看上一篇文章是否与当前文章发生在同一天.这是一个简化的示例.

I'm trying to use a variable declared outside a Go template range loop to see if the previous post occurred on the same day as the current post. Here's a simplified example.

其中 .Posts 是一个 post 结构数组,每个结构都有一个 .Content 和一个 .Date.

Where .Posts is an array of post structs that each have a .Content and a .Date.

{{ $prevDate := "" }}
{{ range $post := .Posts }}
    {{ if ne $prevDate $post.Date }}
        <div class="post-date">Posts dated: {{ $post.Date }}</div>
    {{ end }}
    <div class="post-content">{{ $post.Content }}</div>
    {{ $prevDate := $post.Date }}
{{ end }}

问题是 $prevDate 似乎在循环的每次迭代开始时被重置为 "".

The problem is that $prevDate seems to be reset to "" at the start of each iteration of the loop.

谁能帮我理解为什么每次迭代都会重置 $prevDate 的值,并可能建议一种方法来完成我在这里尝试做的事情?

Can anyone help me understand why the value of $prevDate is reset on each iteration and perhaps suggest a way to accomplish what I'm trying to do here?

推荐答案

注意: Go 1.11 将支持通过赋值修改模板变量.这将是有效代码:

{{ $v := "init" }}
{{ if true }}
  {{ $v = "changed" }}
{{ end }}
v: {{ $v }} {{/* "changed" */}}

Go 1.11 之前的原始答案如下:

Original answer pre-dating Go 1.11 follows:

变量不会被重置.基本上发生的事情是您在循环内重新声明 $prevDate 变量.但它仅在重新声明之后和 {{range}} 的结束 {{end}} 标记之前的范围内.所以当循环的下一次迭代到来时,你只会看到你没有改变的外部"变量(因为你创建了一个新的).

Variables are not reset. Basically what happens is that you redeclare the $prevDate variable inside the loop. But it is only in scope after the redeclaration and before the closing {{end}} tag of the {{range}}. So when the next iteraiton of the loop comes, you only see the "outer" variable which you haven't changed (because you created a new).

您不能更改您创建的模板变量的值.

You can't change the values of the template variables you create.

例如,您可以使用以下 range 形式:

What you can do is for example use the following range form:

{{ range $index, $post := .Posts }}

还有……

并且你可以为模板注册一个函数(参见template.Funcs()) 您可以将 $index 传递给它,它将返回前一个元素的日期字段(在 $index -1).

And you can register a function for the template (see template.Funcs()) to which you can pass the $index and it would return the date field of the previous element (at $index -1).

它看起来像这样:

func PrevDate(i int) string {
    if i == 0 {
        return ""
    }
    return posts[i-1].Date
}

// Registering it:
var yourTempl = template.Must(template.New("").
    Funcs(map[string]interface{}{"PrevDate": PrevDate}).
    Parse(yourStringTemplate))

从你的模板中你可以这样称呼它:

And from your template you can call it like:

{{range $index, $post := .Posts}}
    {{$prevDate := PrevDate $index}}
{{end}}

解决方案#2:使用帖子的方法

这个解决方案是模拟的,但更简单:向您的 Posts 添加一个方法,您可以直接调用它.无需注册函数.

Solution #2: with a Method of Posts

This solution is analog but is even simpler: add a method to your Posts and you can call it directly. No need to register a function.

例如:

type Post struct {
    // Your Post type
    Date string
}

type Posts []Post

func (p *Posts) PrevDate(i int) string {
    if i == 0 {
        return ""
    }
    return (*p)[i-1].Date
}

从你的模板中你可以这样称呼它:

And from your template you can call it like:

{{range $index, $post := .Posts}}
    {{$prevDate := $.Posts.PrevDate $index}}
{{end}}

这篇关于在 Go 模板范围循环中,循环外声明的变量是否在每次迭代时重置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆