duanmangxie7131 2014-11-12 23:11
浏览 456
已采纳

使用golang模板打印以逗号和“或”分隔的列表

It is already elsewhere discussed on stackoverflow that you can print a list separated by comma, as follows:

{{ range $index, $element := .TeamMembers}}
    {{if $index}},{{end}}
    {{$element.Name}}
{{end}}

Is there an easy solution for when you need a list separator that is different for the last item, to include an "or":

{name}, {name}, {name}, or {name}

This is to allow, for example, creation of formatted sentences such as:

The members of this team are Bob, Jane, and Mike.

Any template code I can workout ends up extremely verbose and complicated.

  • 写回答

2条回答 默认 最新

  • douyonglang4845 2014-11-13 05:26
    关注

    Export a function to your template.

    text/template, like some other template systems, doesn't try be good for programming in directly; it just provides a better way to stitch your data and functions with your markup, and you need to write other presentational code when it's insufficient. You can write a yourapp/template module that exports a version of New() that calls Funcs() to add the common functions you use.

    (You might find uses for a lot more functions than just these; Django, for example, offers lots of builtins for pluralization, formatting, i18n, etc., and folks still often extend the set.)

    package main // package mytemplate
    
    import (
        "fmt"
        "os"
        "strings"
        "text/template"
    )
    
    func conjoin(conj string, items []string) string {
        if len(items) == 0 {
            return ""
        }
        if len(items) == 1 {
            return items[0]
        }
        if len(items) == 2 { // "a and b" not "a, and b"
            return items[0] + " " + conj + " " + items[1]
        }
    
        sep := ", "
        pieces := []string{items[0]}
        for _, item := range items[1 : len(items)-1] {
            pieces = append(pieces, sep, item)
        }
        pieces = append(pieces, sep, conj, " ", items[len(items)-1])
    
        return strings.Join(pieces, "")
    }
    
    // if you use some funcs everywhere have some package export a Template constructor that makes them available, like this:
    
    var commonFuncs = template.FuncMap{
        "andlist": func(items []string) string { return conjoin("and", items) },
        "orlist":  func(items []string) string { return conjoin("or", items) },
    }
    
    func New(name string) *template.Template {
        return template.New(name).Funcs(commonFuncs)
    }
    
    func main() {
        // test conjoin
        fmt.Println(conjoin("or", []string{}))
        fmt.Println(conjoin("or", []string{"Bob"}))
        fmt.Println(conjoin("or", []string{"Bob", "Mike"}))
        fmt.Println(conjoin("or", []string{"Bob", "Mike", "Harold"}))
    
        people := []string{"Bob", "Mike", "Harold", "Academy Award nominee William H. Macy"}
        data := map[string]interface{}{"people": people}
        tmpl, err := New("myyy template").Parse("{{ orlist .people }} / {{ andlist .people }}")
        if err != nil {
            fmt.Println("sadness:", err.Error())
            return
        }
        err = tmpl.Execute(os.Stdout, data)
        if err != nil {
            fmt.Println("sadness:", err.Error())
            return
        }
    }
    

    Here's a variation that also exports "conjoin", and an "isLast" function you can use in a kind of verbose construction to do some arbitrary thing differently in the last go through the loop.

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

报告相同问题?

悬赏问题

  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?