如何使用go

时间:2017-10-22 14:16:37

标签: go go-templates

我在json中有一些数据

[
    {
        "group":"a",
        "value":"10"

    },
    {
        "group":"a",
        "value":"11"

    },
    {
        "group":"b",
        "value":"2"

    },
    {
        "group":"b",
        "value":"3"

    }
]

或作为一个表格,以便于阅读...

group   value
a       10
a       11
b       2
b       3

我想按group排名

group   value     rank
a       10        1
a       11        2
b       2         1 
b       3         2

在其他语言中,我会使用一个计数器循环数据,当有一个新的group值时,该计数器会重置。我可以通过数据,但我不能让计数器工作。在下面的例子中,似乎前一个计数器值没有保留在下一次迭代中,因此每个值都是1.

{{ $counter := 1 }}

{{- range $index, $element := $data }}

  {{ inline (gt $index 0) "," "" }} 

  { 
  "group" : "{{ .group }}", 
  "value" : "{{ .value }}", 
  "rank" : "{{ $counter }}" 
  {{ $counter := add $counter 1 }}
  }

{{- end -}}

1 个答案:

答案 0 :(得分:0)

在显示例程中实现这种逻辑与go模板的设计原理相反,并且通常违反separation of concerns的概念。

也就是说,模板是 display (或“表示”)关注点,而如您在此处描述的那样,排名是 ordering (或“业务逻辑”)关注点。通过在显示组件中执行排序,您使程序变得脆弱,因为这些顾虑不能彼此独立地更改,也不能在一般意义上重复使用。例如,如果要将元素打印为JSON或YAML数据(包括其排名),则必须重新实现在文本模板中编写的排名逻辑;如果排名由于某种原因发生了变化,那么您将不得不在多个位置进行更改。

更好的方法是创建一个功能,以按需排列元素,而与您如何显示它们无关。这样,您的程序可以在许多方面更强大,主要是因为您只需要在项目更改时才对其进行排名,而不是每次显示它们时都需要对其进行排名。

例如(Go Playground):

type Item struct {
  Group string `json:"group"`
  Value int    `json:"value,string"`
  Rank  int    `json:"rank,omitempty"`
}

func main() {
  // Parse the items.
  var items []Item
  err := json.Unmarshal([]byte(jsonstr), &items)
  check(err)

  // Rank the items.
  RankItems(items)

  // Display the items.
  PrintTable(items)
  PrintJSON(items)
  PrintYAML(items) // etc...
}

func RankItems(xs []Item) {
  // Order the items by group, value.
  sort.Slice(xs, func(i, j int) bool {
    x1, x2 := xs[i], xs[j]
    if x1.Group == x2.Group {
      return x1.Value < x2.Value
    }
    return x1.Group < x2.Group
  })
  // Rank the items by position within a group.
  var lastGroup string
  var nextRank int
  for i := range xs {
    if i == 0 || lastGroup != xs[i].Group {
      nextRank = 1
    }
    xs[i].Rank = nextRank
    lastGroup = xs[i].Group
    nextRank++
  }
}