迭代 Go 地图获取索引

DiC*_*rio 6 dictionary go go-templates revel

为了在模板中使用revel'seven关键字,我想在使用range. 有什么办法吗?我的地图具有以下结构:

map[string][]string
Run Code Online (Sandbox Code Playgroud)

Edw*_*Guo 14

循环遍历地图时实现索引的简单方法:

package main

import (
    "fmt"
)

func main() {
    mm := map[string]int{"xx" : 1, "gg" : 2}
    cnt := 0
    for a, b:= range mm{
        fmt.Println("a", a, "b",b, "c" , cnt)
        cnt++
    }
    fmt.Println("Hello, playground")
}
Run Code Online (Sandbox Code Playgroud)

并打印:

a xx b 1 c 0
a gg b 2 c 1
Hello, playground
Run Code Online (Sandbox Code Playgroud)


icz*_*cza 3

您不能仅使用模板操作来执行此操作,但您可以注册一个提供必要帮助的函数。

您可以注册一个返回函数(闭包)的函数,该函数在每次调用时都会交替其返回值(“奇数”和“偶数”索引究竟如何交替):

func isEven() func() bool {
    e := false
    return func() bool {
        e = !e
        return e
    }
}
Run Code Online (Sandbox Code Playgroud)

我命名它是isEven()为了不与拉威尔的冲突even()。使用它:

func main() {
    t := template.Must(template.New("").Funcs(template.FuncMap{
        "isEven": isEven,
    }).Parse(templ))

    m := map[string]string{
        "a": "A", "b": "B", "c": "C", "d": "D",
    }
    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
}

const templ = `{{$e := isEven}}
{{- range $k, $v := . -}}
    [even:{{call $e}}] key={{$k}}; value={{$v}}
{{end}}`
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上尝试):

[even:true] key=a; value=A
[even:false] key=b; value=B
[even:true] key=c; value=C
[even:false] key=d; value=D
Run Code Online (Sandbox Code Playgroud)

如果您希望奇数和偶数迭代有不同的输出,您可以调用$e一个{{if}}操作,如下所示:

const templ = `{{$e := isEven}}
{{- range $k, $v := . -}}
    [{{if call $e}}even{{else}}odd {{end}}] key={{$k}}; value={{$v}}
{{end}}`
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上尝试):

[even] key=a; value=A
[odd ] key=b; value=B
[even] key=c; value=C
[odd ] key=d; value=D
Run Code Online (Sandbox Code Playgroud)

在引擎盖下

该模板操作:

{{$e := isEven}}
Run Code Online (Sandbox Code Playgroud)

创建一个名为 的新模板变量$e,其值将是函数调用的结果(返回值)isEven()isEven()返回一个函数值,一个可以访问e类型的局部变量的闭包bool。当稍后你这样做时{{call $e}},你不是在调用isEven()Go 函数,而是它返回的函数(闭包)并存储在$e. bool该闭包具有对局部变量的引用e,直到函数返回时它才被“释放”isEvent()访问时它才会被“释放”。

因此,每当您这样做时{{call $e}},它都会调用闭包,该闭包“具有”e类型为 的变量bool,其值在 this 的调用之间保留$e

如果您isEvent再次调用模板,则会返回一个新函数(闭包),包装局部变量的新实例e,独立于第一次调用返回的闭包的第一个包装变量isEvent()

  • @Mrlenny 添加了一个新的 **Under the hood** 部分来解释内部结构。 (2认同)