droos02800 2017-03-22 10:12
浏览 55
已采纳

迭代Go地图获取索引

In order to use revel's even keyword in templates I would like to get the index of a map entry when iterating with range. Is there any way to do so? My map has the structure:

map[string][]string
  • 写回答

4条回答 默认 最新

  • douzachan4578 2017-03-22 11:20
    关注

    You can't do this only with template actions, but you may register a function which provides the necessary help.

    You may register a function which returns a function (closure), which alternates its return value whenever called (exactly how "odd" and "even" indices alternate):

    func isEven() func() bool {
        e := false
        return func() bool {
            e = !e
            return e
        }
    }
    

    I named it isEven() to not collide with ravel's even(). Using it:

    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}}`
    

    Output (try it on the 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
    

    If you want different output for odd and even iterations, you can call $e in an {{if}} action, like this:

    const templ = `{{$e := isEven}}
    {{- range $k, $v := . -}}
        [{{if call $e}}even{{else}}odd {{end}}] key={{$k}}; value={{$v}}
    {{end}}`
    

    Output of this (try it on the Go Playground):

    [even] key=a; value=A
    [odd ] key=b; value=B
    [even] key=c; value=C
    [odd ] key=d; value=D
    

    Under the hood

    This template action:

    {{$e := isEven}}
    

    Creates a new template variable named $e, and its value will be the result (return value) of the isEven() function call. isEven() returns a function value, a closure that has access to a local variable e of type bool. When later you do {{call $e}}, you're not calling the isEven() Go function, but the function it returned (the closure) and is stored in $e. That closure has a reference to the local bool variable e, it is not "freed" until the function returned by isEvent() is accessible.

    So whenever you do {{call $e}}, it calls the closure, which "has" an e variable of type bool, whose value is retained between calls of this $e.

    If you would call isEvent in the template again, that would return a new function (closure), wrapping a new instance of the local variable e, being independent of the first wrapped variable of the closure returned by the first isEvent() call.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 linux驱动,linux应用,多线程
  • ¥20 我要一个分身加定位两个功能的安卓app
  • ¥15 基于FOC驱动器,如何实现卡丁车下坡无阻力的遛坡的效果
  • ¥15 IAR程序莫名变量多重定义
  • ¥15 (标签-UDP|关键词-client)
  • ¥15 关于库卡officelite无法与虚拟机通讯的问题
  • ¥15 目标检测项目无法读取视频
  • ¥15 GEO datasets中基因芯片数据仅仅提供了normalized signal如何进行差异分析
  • ¥100 求采集电商背景音乐的方法
  • ¥15 数学建模竞赛求指导帮助