определить последний элемент внутри массива, используя диапазон внутри go-templates

Эта программа выводит просто

1,4,2,

но я хотел бы распечатать

1,4,2.

Как видите, запятая печатается после каждого элемента массива.

package main

import "os"
import "text/template"

func main() {
    params := map[string]interface{}{
        "items": [3]int{1, 4, 2},
    }
    tpl := "{{range $i, $el := .items}}{{$el}},{{end}}"
    lister, _ := template.New("foo").Parse(tpl)
    lister.Execute(os.Stdout, params)
}

Есть ли способ изменить {{range $i, $el := .items}}{{$el}},{{end}} и убедиться, что последний элемент будет печатать "." вместо ","


person sensorario    schedule 29.04.2018    source источник
comment
Возможный дубликат stackoverflow.com/questions/10747054/, stackoverflow.com/questions/21305865/   -  person Cerise Limón    schedule 29.04.2018


Ответы (2)


Ты можешь использовать

tpl := "{{range $i, $el := .items}}{{if $i}},{{end}}{{$el}}{{end}}."

чтобы добиться этого. Хитрость заключается в том, чтобы сначала выделить разделитель запятой, но не для первого элемента в диапазоне.

person fhe    schedule 29.04.2018
comment
Это заставляет меня улыбаться, но это работает ^_^. Я не обнаружил последние элементы, ... но решил проблему. Большое спасибо ^_^ - person sensorario; 29.04.2018
comment
Если вам не нужна конечная точка в случае пустого списка, используйте этот вариант ответа {{with .items}}{{range $i, $el := .}}{{if $i}},{{end}}{{$el}}{{end}}.{{end}} - person Cerise Limón; 29.04.2018

В опубликованном вами простом примере проще всего то, что опубликовал "fhe": вы можете легко проверить, является ли текущий индекс первым, и вывести запятую после не первых элементов. И, наконец, выведите завершающую точку.

Если в более сложном примере вам нужно обнаружить последний элемент, или может случиться так, что список, который вы перебираете, может быть пустым (и, таким образом, конечная точка будет ошибкой), вы можете зарегистрировать пользовательскую функцию, чтобы узнать, если текущий индекс является последним:

lister := template.Must(template.New("foo").Funcs(template.FuncMap{
    "IsLast": func(i, size int) bool { return i == size-1 },
}).Parse(tpl))

Затем используйте следующий шаблон:

tpl := "{{range $i, $el := .items}}{{$el}}{{if IsLast $i (len $.items)}}.{{else}},{{end}}{{end}}"

Результат будет таким (попробуйте на Go Playground):

1,4,2.

Вариантом этого может быть регистрация пользовательской функции, которая вычисляет последний индекс по длине (lastIdx = length - 1), а затем внутри {{range}} вы можете выполнить простое сравнение:

tpl := "{{$lastIdx := LastIdx (len .items)}}{{range $i, $el := .items}}{{$el}}{{if eq $lastIdx $i}}.{{else}},{{end}}{{end}}"
lister := template.Must(template.New("foo").Funcs(template.FuncMap{
    "LastIdx": func(size int) int { return size - 1 },
}).Parse(tpl))

Выход будет таким же. Попробуйте на Go Playground.

person icza    schedule 29.04.2018
comment
Вместо Ты вдохновил меня!! Вместо создания функции я могу передать напрямую номер элемента массива: {{range $i, $el := .items}}{{$el}}{{if eq $i $.last}}.{ {еще}},{{конец}}{{конец}} - person sensorario; 29.04.2018
comment
@sensorario Да, в одном случае это даже проще. Может быть больше хлопот и работы, если вам это нужно во многих местах. - person icza; 29.04.2018