Соединить блок диапазона в шаблоне go - PullRequest
0 голосов
/ 26 июня 2018

У меня есть шаблон go, подобный этому:

 "environment": [
   {{- range $k,$v := .env }}
     {
       "name": "{{ $k }}",
       "value": "{{ $v }}"
     },
   {{- end }}
   ]

и я получаю вывод ниже:

     "environment": [
    {
      "name": "name",
      "value": "test"
    },
    {
      "name": "region",
      "value": "us-east-1"
    },
  ]

и я хочу сделать это, как показано ниже:

    "environment": [
    {
      "name": "name",
      "value": "bxbd"
    },
    {
      "name": "region",
      "value": "us-east-1"
    }
  ]

Я не могу избавиться от последней запятой, чтобы сделать правильный JSON. Или можно как-то отправить полный блок диапазона в какую-нибудь пользовательскую функцию соединения?

1 Ответ

0 голосов
/ 26 июня 2018

Вот пример того, как сделать это с шаблонами, но я настоятельно рекомендую использовать 2-й подход, если вы хотите сгенерировать JSON.

Наклейка с шаблонами

Поскольку вы перемещаетесь по карте, вы не можете (просто) сделать это. В случае срезов вы можете проверить индексную переменную (примеры: Шаблон Go удаляет последнюю запятую в цикле диапазона ; и обнаруживает последний элемент внутри массива, используя диапазон внутри go-шаблонов ), но в случае карт вы не можете этого сделать.

Знание того, находитесь ли вы на первой (или последней) итерации, является состоянием , которое вы должны поддерживать сами. И пример - использовать пользовательские функции или методы для этого.

Вот пример реализации:

type Params struct {
    Env     map[string]string
    Counter int
}

func (p *Params) IncMore() bool {
    p.Counter++
    return p.Counter < len(p.Env)
}

const src = `"environment": [
   {{- range $k,$v := .Env }}
     {
       "name": "{{ $k }}",
       "value": "{{ $v }}"
     }{{if $.IncMore}},{{end}}
   {{- end }}
   ]`

Тестирование:

func main() {
    t := template.Must(template.New("").Parse(src))
    p := &Params{
        Env: map[string]string{
            "name":   "test",
            "region": "us-east-1",
        },
    }
    err := t.Execute(os.Stdout, p)
    if err != nil {
        panic(err)
    }
}

Вывод (попробуйте на Go Playground ):

"environment": [
     {
       "name": "name",
       "value": "test"
     },
     {
       "name": "region",
       "value": "us-east-1"
     }
   ]

Используйте encoding/json для генерации JSON

Если ваша цель - сгенерировать JSON, вы должны использовать пакет encoding/json для создания действительного документа JSON. Приведенный выше шаблон не знает синтаксиса и контекста JSON, и значения записей карты не экранируются при записи в вывод, поэтому вы все равно можете получить недопустимый JSON.

Лучше всего сгенерировать JSON следующим образом:

type Entry struct {
    Name  string `json:"name"`
    Value string `json:"value"`
}

type Params struct {
    Env []Entry `json:"environment"`
}

func main() {
    enc := json.NewEncoder(os.Stdout)
    enc.SetIndent("", "  ") // Optional
    p := &Params{
        Env: []Entry{
            {Name: "name", Value: "test"},
            {Name: "region", Value: "us-east-1"},
        },
    }
    err := enc.Encode(p)
    if err != nil {
        panic(err)
    }
}

Вывод (попробуйте на Go Playground ):

{
  "environment": [
    {
      "name": "name",
      "value": "test"
    },
    {
      "name": "region",
      "value": "us-east-1"
    }
  ]
}
...