如何在 golang 模板中计算一列的总和?

huangapple go评论128阅读模式
英文:

How to calculate a total for a column inside a golang template?

问题

我在html/template中有这段代码:

  1. {{ $TotalPrice := 0.0 }}
  2. {{ range $i, $tx := .Transactions }}
  3. {{ $TotalPrice := FloatInc $TotalPrice (StrToFloat .TotalPrice) }}
  4. <tr>
  5. <td>{{ inc $i 1 }}</td>
  6. <td>{{ .Description.String }}</td>
  7. <td>{{ .Type }}</td>
  8. <td>{{ .TotalPrice }}</td>
  9. <td>{{ .Note }}</td>
  10. </tr>
  11. {{ end }}
  12. <tr>
  13. <td></td>
  14. <td></td>
  15. <td></td>
  16. <td>{{ $TotalPrice }}</td>
  17. <td></td>
  18. <td></td>
  19. </tr>

Transactions是带有TotalPrice DB字段的货币交易,根据Iris框架的规范,我有4个函数。

  1. tmpl.AddFunc("dec", func(num int, step int) int {
  2. return num - step
  3. })
  4. tmpl.AddFunc("inc", func(num int, step int) int {
  5. return num + step
  6. })
  7. tmpl.AddFunc("FloatDec", func(num float64, step float64) float64 {
  8. return num - step
  9. })
  10. tmpl.AddFunc("FloatInc", func(num float64, step float64) float64 {
  11. return num + step
  12. })
  13. tmpl.AddFunc("StrToFloat", func(s string) (float64, error) {
  14. return strconv.ParseFloat(s, 64)
  15. })

我注意到$TotalPrice在每次迭代中保持初始值(0.0),所以在range内部的{{ $TotalPrice }}将打印.TotalPrice的值,并且最后一行的$TotalPrice的值也将为0.0。那么在go模板中,以下代码的等效写法是什么:

  1. nums := []int{2, 3, 4}
  2. sum := 0
  3. for _, num := range nums {
  4. sum += num
  5. }
  6. fmt.Println("sum:", sum)
英文:

I have this code inside a html/template:

  1. {{ $TotalPrice := 0.0 }}
  2. {{ range $i, $tx := .Transactions }}
  3. {{ $TotalPrice := FloatInc $TotalPrice (StrToFloat .TotalPrice) }}
  4. &lt;tr&gt;
  5. &lt;td&gt;{{ inc $i 1 }}&lt;/td&gt;
  6. &lt;td&gt;{{ .Description.String }}&lt;/td&gt;
  7. &lt;td&gt;{{ .Type }}&lt;/td&gt;
  8. &lt;td&gt;{{ .TotalPrice }}&lt;/td&gt;
  9. &lt;td&gt;{{ .Note }}&lt;/td&gt;
  10. &lt;/tr&gt;
  11. {{ end }}
  12. &lt;tr&gt;
  13. &lt;td&gt;&lt;/td&gt;
  14. &lt;td&gt;&lt;/td&gt;
  15. &lt;td&gt;&lt;/td&gt;
  16. &lt;td&gt;{{ $TotalPrice }}&lt;/td&gt;
  17. &lt;td&gt;&lt;/td&gt;
  18. &lt;td&gt;&lt;/td&gt;
  19. &lt;/tr&gt;

Transactions are Money Transaction with TotalPrice DB Fields and I have 4 functions according Iris framework spec.

  1. tmpl.AddFunc(&quot;dec&quot;, func(num int, step int) int {
  2. return num - step
  3. })
  4. tmpl.AddFunc(&quot;inc&quot;, func(num int, step int) int {
  5. return num + step
  6. })
  7. tmpl.AddFunc(&quot;FloatDec&quot;, func(num float64, step float64) float64 {
  8. return num - step
  9. })
  10. tmpl.AddFunc(&quot;FloatInc&quot;, func(num float64, step float64) float64 {
  11. return num + step
  12. })
  13. tmpl.AddFunc(&quot;StrToFloat&quot;, func(s string) (float64, error) {
  14. return strconv.ParseFloat(s, 64)
  15. })

I've note the $TotalPrice keeps the initial value (0.0) for every iteration so {{ $TotalPrice }} inside the range will print the .TotalPrice value and the value of $TotalPrice at the last row will be 0.0 too then what is the equivalent, inside go template, of:

  1. nums := []int{2, 3, 4}
  2. sum := 0
  3. for _, num := range nums {
  4. sum += num
  5. }
  6. fmt.Println(&quot;sum:&quot;, sum)

答案1

得分: 3

在Go的模板中,一旦声明了一个变量并给它赋值,就不能更改其值。在你的代码中发生的情况如下:

  1. 外部总价格的值被声明为$TotalPrice := 0.0,始终为0.0,并且变量的作用域延伸到模板的末尾。
  2. 当你在range内部定义一个名为$TotalPrice的变量时,尽管变量名相同,但会分配一个全新的变量。这个变量的值由FloatInc($TotalPrice, .TotalPrice)给出。注意,参数$TotalPrice指的是外部的总价格,即0.0,所以这个语句相当于$TotalPrice := 0.0 + .TotalPrice。因此,当你在每次迭代中打印$TotalPrice时,你得到的是当前的.TotalPrice,而不是累积的总价格。
  3. 在(2)中声明的变量的作用域在rangeend之间。因此,当你在最后一行打印$TotalPrice时,你得到的是在(1)中声明的外部总价格的值,即0.0

在你的情况下,你需要声明一个函数,该函数以Transactions作为参数,然后在函数内部计算总和,例如:

  1. tmpl.AddFunc("sum", func(transactions []Transaction) float64 {
  2. sum := 0.0
  3. for _, t := range transactions {
  4. if v, err := strconv.ParseFloat(t.TotalPrice, 64); err == nil {
  5. sum += v
  6. }
  7. }
  8. return sum
  9. })

然后在模板中使用它:

  1. {{ $TotalPrice := sum .Transactions }}
英文:

In Go's template, once you declare a variable and assign value to it, you can't change its value. What happen in your code are:

  1. The value of outer total price which is declared as $TotalPrice := 0.0 is always 0.0, and the variable scope is extended to the end of the template.
  2. When you defined a variable named $TotalPrice inside range, although the variable name is the same, a completely new variable will be allocated. The value assigned to this variable is given by FloatInc($TotalPrice, .TotalPrice). Note that argument $TotalPrice refers to outer total price which is 0.0, so the statement will be equal to $TotalPrice := 0.0 + .TotalPrice. Thus, when you print the $TotalPrice in each iteration, you got current .TotalPrice instead of accumulated total price.
  3. The scope of variable declared in (2) is between range and end. Thus when you print $TotalPrice at the last row, you got the value of outer total price declared in (1), i.e. 0.0.

In your case, you need to declare a function which takes Transactions as its argument then calculate the total inside the function, e.g.

  1. tmpl.AddFunc(&quot;sum&quot;, func(transactions []Transaction) float64 {
  2. sum := 0.0
  3. for _, t := range transactions {
  4. if v, err := strconv.ParseFloat(t.TotalPrice, 64); err == nil {
  5. sum += v
  6. }
  7. }
  8. return sum
  9. })

then use it in the template as:

  1. {{ $TotalPrice := sum .Transactions }}

huangapple
  • 本文由 发表于 2017年8月29日 09:35:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/45929461.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定