英文:
Go templates with eq and index
问题
Go模板在使用eq
和index
时对我来说产生了一些意外的结果。看看这段代码:
package main
import (
"os"
"text/template"
)
func main() {
const myTemplate = `
{{range $n := .}}
{{index $n 0}} {{if (index $n 0) eq (index $n 1)}}={{else}}!={{end}} {{index $n 1}}
{{end}}
`
t := template.Must(template.New("").Parse(myTemplate))
t.Execute(os.Stdout,
[][2]int{
[2]int{1, 2},
[2]int{2, 2},
[2]int{4, 2},
})
}
我期望输出为:
1 != 2
2 = 2
4 != 2
但实际上我得到了:
1 = 2
2 = 2
4 = 2
我应该如何修改才能在Go模板中比较数组成员?
英文:
Go templates have some unexpected results when using eq
with index
for me. See this code:
package main
import (
"os"
"text/template"
)
func main() {
const myTemplate = `
{{range $n := .}}
{{index $n 0}} {{if (index $n 0) eq (index $n 1)}}={{else}}!={{end}} {{index $n 1}}
{{end}}
`
t := template.Must(template.New("").Parse(myTemplate))
t.Execute(os.Stdout,
[][2]int{
[2]int{1, 2},
[2]int{2, 2},
[2]int{4, 2},
})
}
I expect to have output
1 != 2
2 = 2
4 != 2
but I get
1 = 2
2 = 2
4 = 2
What should I change to be able to compare array members in go templates?
答案1
得分: 15
eq
是一个前缀操作:
{{if eq (index $n 0) (index $n 1)}}={{else}}!={{end}}
Playground: http://play.golang.org/p/KEfXH6s7N1.
英文:
eq
is a prefix operation:
{{if eq (index $n 0) (index $n 1)}}={{else}}!={{end}}
Playground: http://play.golang.org/p/KEfXH6s7N1.
答案2
得分: 7
你使用了错误的运算符和参数顺序。你需要先写运算符,然后是操作数:
{{if eq (index $n 0) (index $n 1)}}
这样更易读和方便,因为eq
可以接受多个参数,所以你可以写成:
{{if eq (index $n 0) (index $n 1) (index $n 2)}}
对于更简单的多路相等测试,
eq
(仅)接受两个或多个参数,并将第二个及后续参数与第一个进行比较,实际上返回
arg1==arg2 || arg1==arg3 || arg1==arg4 ...
(不过,与Go中的||不同,
eq
是一个函数调用,所有参数都将被求值。)
通过这个改变,输出结果如下(在Go Playground上尝试):
1 != 2
2 = 2
4 != 2
注意:
你不需要引入一个“循环”变量,{{range}}
操作会将点(dot)更改为当前项:
...dot is set to the successive elements of the array, slice, or map...
所以你可以简化你的模板,下面的模板与你的等价:
{{range .}}
{{index . 0}} {{if eq (index . 0) (index . 1)}}={{else}}!={{end}} {{index . 1}}
{{end}}
另外请注意,你可以在模板中自己创建变量,如果你多次使用相同的表达式且表达式非平凡(比如index . 0
),这是推荐的做法。下面的模板也与你的模板等价:
{{range .}}{{$0 := index . 0}}{{$1 := index . 1}}
{{$0}} {{if eq $0 $1}}={{else}}!={{end}} {{$1}}
{{end}}
还要注意,在这种特殊情况下,由于你想要在if
和else
分支中输出的内容都包含=
符号,你不需要两个分支,=
需要在两种情况下输出,只需要在它们不相等时加一个额外的!
符号。所以下面的最终模板也与你的模板等价:
{{range .}}{{$0 := index . 0}}{{$1 := index . 1}}
{{$0}} {{if ne $0 $1}}!{{end}}= {{$1}}
{{end}}
英文:
You use wrong operator and argument order. You have to first write the operator and then the operands:
{{if eq (index $n 0) (index $n 1)}}
This is more readable and handy as eq
can take more than just 2 arguments, so you could write for example:
{{if eq (index $n 0) (index $n 1) (index $n 2)}}
> For simpler multi-way equality tests, eq (only) accepts two or more arguments and compares the second and subsequent to the first, returning in effect
> arg1==arg2 || arg1==arg3 || arg1==arg4 ...
> (Unlike with || in Go, however, eq is a function call and all the arguments will be evaluated.)
With this change the output (try it on the Go Playground):
1 != 2
2 = 2
4 != 2
Note:
You are not required to introduce a "loop" variable, the {{range}}
action changes the dot to the current item:
> ...dot is set to the successive elements of the array, slice, or map...
So you can simplify your template, this is equivalent to yours:
{{range .}}
{{index . 0}} {{if eq (index . 0) (index . 1)}}={{else}}!={{end}} {{index . 1}}
{{end}}
Also note that you can create variables in the template yourself, which is recommended if you use the same expression multiple times which is nontrivial (such as index . 0
). This is also equivalent to your template:
{{range .}}{{$0 := index . 0}}{{$1 := index . 1}}
{{$0}} {{if eq $0 $1}}={{else}}!={{end}} {{$1}}
{{end}}
Also note that in this specific case since the things you want to output in the if
and else
branches both contain the =
sign, you don't need 2 branches, =
needs to be outputted in both cases, you just need an extra !
sign if they are not equal. So the following final template is also equivalent to yours:
{{range .}}{{$0 := index . 0}}{{$1 := index . 1}}
{{$0}} {{if ne $0 $1}}!{{end}}= {{$1}}
{{end}}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论