Golang : How to pass map to html template and access the map’s elements
For this tutorial, we will learn how to pass a map to text or html template and learn how to access the map’s element. The first code snippet demonstrates the simplest way of creating a map, passing it to html/text template and access the map’s element using the index keyword.
NOTE : The «index» can also be used for accessing slice and array.
NOTE : If you encounter «panic: assignment to entry in nil map» error. Use the make keyword to create your map instead. For example :
var templateDataMap = make(map[string]interface<>)
var templateDataMap map[string]interface<> //-- will cause panic: assignment to entry in nil map
package main import ( "html/template" "log" "os" ) const html = `> > > > > >` func main() < Data := map[int]string<>Data[1] = "abc" Data[2] = "def" Data[3] = "ghi" firstTemplate, err := template.New("first").Parse(html) if err != nil < log.Fatalln(err) >err = firstTemplate.ExecuteTemplate(os.Stdout, "first", Data) if err != nil < log.Fatalln(err) >>
and the second code snippet demonstrates a slightly different way, but still produces the same output. The difference is that we will pass the map name as well. This will be useful in situation where we want to pass more than 1 map and able to distinguish them using the maps’ names.
package main import ( "html/template" "log" "os" ) const html = ` > > > > > > ` var templateDataMap = make(map[string]interface<>) //var templateDataMap map[string]interface<> -- will cause panic: assignment to entry in nil map func main() < DataMap := map[int]string<>DataMap[1] = "abc" DataMap[2] = "def" DataMap[3] = "ghi" templateDataMap["DataMap"] = DataMap // pass the map's name as well var secondTemplate = template.Must(template.New("second").Parse(html)) if err := secondTemplate.ExecuteTemplate(os.Stdout, "second", templateDataMap); err != nil < log.Fatalln(err) >>
Hope this helps and happy coding!
«index Returns the result of indexing its first argument by the following arguments. Thus «index x 1 2 3″ is, in Go syntax, x1[2][3]. Each indexed item must be a map, slice, or array.»
See also : Golang : Executing and evaluating nested loop in html template
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
GO templates
Пакеты text/template , html/template являются частью стандартной библиотеки GO. Шаблоны GO используются во многих решениях на базе языка, таких как docker , kubernetes , helm . С ними интегрированы также многие web-библиотеки, например echo. Понимание синтаксиса встроенного шаблонизатора GO полезно в очень многих задачах.
Данная статья содержит адаптированные материалы из документации к пакету text/template и несколько решений из опыта автора. После описания стандартных возможностей, для более глубокого понимания рассмотрим исходники пакетов text/template и html/template .
Шаблоны GO являются активными, что позволяет использовать в них управляющие конструкции, такие как if , else , циклы range .
Не смотря на четкую типизацию языка GO, шаблонизатор работает с любыми данными, достигается это использованием пакета reflect .
Все инструкции шаблона заключаются в символы > . Текст вне этих символов является не вызовами шаблонизатора, а простым текстом. Простой текст копируется из шаблона в вывод без какого-либо изменения.
Для запуска шаблона со стороны GO-кода у нас есть функции Execute и ExecuteTemplate . В них обоих есть параметр data interface<> .
Execute(wr io.Writer, data interface>) error ExecuteTemplate(wr io.Writer, name string, data interface>) error
Здесь данные, переданные через параметр data — те, с которыми шаблон работает по умолчанию. Из шаблона они доступны как . . Для вывода текущих данных достаточно следующего:
Будем называть данные, доступные через . , текущим контекстом шаблона. Некоторые конструкции изменяют этот контекст.
Далее рассмотрим синтаксические компоненты шаблонизатора GO.
Если condition будет равен 0 , «» , nil , или пустым массивом, срезом, это будет воспринято как false . В остальных случаях — инструкция T1 выполнится.
Допустимы вариации с else , else if :
if condition>> T1 else>> T0 end>> if condition1>> T1 else if condition2>> T0 end>>
Итерировать в цикле можно массивы, срезы, карты и каналы. На каждую итерацию будет вызвана инструкция T1, при этом контекст шаблона будет переключен на элемент конкретной итерации.
Также возможна вариация с else , который выполнится если somelist пуст:
range somelist>> T1 else>> T2 end>>
Можно получить ключи и значения каждого элемента в переменные:
range $key, $value := somelist>> $key >>: $value >> end>>
В данном случае к pipeline применяется проверка, будто бы мы используем if . Если значение pipeline будет эквивалентно true (cм описание if ), инструкция T1 выполнится. При этом текущий контекст этой инструкции изменится на pipeline.
Шаблон задать можно следующими двумя конструкциями:
Запустить шаблон c данными context:
Элементы карт, поля структур, вызовы методов
Шаблоны GO могут выводить различные значения.
Наример, поля структуры или значения их мапы. Поля структуры для использования в шаблоне должны быть экспотируемы (начинаться с большой буквы).
Ключи мапы могут начинаться с буквы любого регистра.
Можно выстраивать цепочки их получения:
Можно использовать вызовы методов. Функция или метод для использования в шаблоне должны удовлетворять одному из условий:
- возвращаемое значение функции или метода должно быть одно;
- возвращаемых значений два, но второе — error ;
В исходниках пакета text/template присуствует код проверки вызываемых функций/методов на соответствие этим условиям.
Следующий код на GO подготавливает метод для вызова в шаблоне:
type myType struct> func(m *myType) Method() string return "123" >
Код шаблона вызывает метод:
В шаблонизаторе GO два типа функций — встроенные и пользовательские.
Вызов функции любого типа выглядит так:
Список стандартных функций:
- call funcLocation arg1 arg2 — встроенная функция call позволяет вызывать другие функции, например функции, хранящиеся в переменных или чье имя находится в переменной;
- index x 1 2 3 — получение элемента среза/массива/мапы;
- slice x 1 2 — получение нового среза из среза, аналогично s[1:2] ;
- len x — получение длины среза/массива/мапы;
- print , printf , println — явный вывод данных;
Булевы операторы в шаблонах также реализованы как функции:
- eq arg1 arg2 — arg1 == arg2
- ne arg1 arg2 — arg1 != arg2
- lt arg1 arg2 — arg1
- le arg1 arg2 — arg1
- gt arg1 arg2 — arg1 > arg2
- ge arg1 arg2 — arg1 >= arg2
Можно определить функцию в коде на GO и затем использовать ее в шаблонах. Ниже приведен GO-код функции last , которая помогает определить, является ли элемент последним в списке:
tempTemplate := template.New("main").Funcs( template.FuncMap "last": func(x int, a interface>) bool return x == reflect.ValueOf(a).Num()-1 >, >)
$allKeywords := .Data.Keywords >> range $k,$v := .Data.Keywords>> $v >> if ne (last $i $allKeywords) >>, end >> end >>
Шаблоны GO используют пакет reflect . Например, конструкция range релизована следующим образом в text/template :
func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) // . switch val.Kind() case reflect.Array, reflect.Slice: // . case reflect.Map: // . case reflect.Chan: // . >
Для каждой конструкции шаблонов написана реализация, которая работает с любым стандартным типом данных через пакет reflect , например так работает получение поля структуры. html/template во многом использует text/template . Особенностью html/template является то, что шаблонизатор понимает, какой именно html-контент в данный момент выводится шаблоном (html-тэг, атрибут, тело тэга, css-контент, URL) и исходя из этого применяет разные способы экранирования, не ломая при этом внешнюю структуру html, что является хорошим преимуществом данного шаблонизатора.
Другие статьи
GO templates
Packages text/template , html/template are part of GO standard library. GO templates are used in many GO-programmed software — docker , kubernetes , helm . Many 3rd party libraries are integrated with GO templates, for example echo. Knowing GO templates syntax is pretty useful.
This article consists of text/template package documentation and couple of author’s solutions. After describing GO templates syntax we’ll dive into text/template и html/template sources.
GO templates are active, which means flow-control instructions such as if , else , range cycles are available here.
GO is strictly typed language, but templates work with all data types, many thanks to reflect package developers.
Let’s take a brief look to GO templates syntax basics.
All template instructions are set between > symbols. Any other text is just plain text that is simply printed to output without any changes.
We have Execute и ExecuteTemplate GO functions to run templates. Both of them have data interface<> parameter.
Execute(wr io.Writer, data interface>) error ExecuteTemplate(wr io.Writer, name string, data interface>) error
data parameter here is a default template data. It can be accessed from templates as . . Following code prints default data:
Let’s call default data current template context. Some template instructions can change template context.
Далее рассмотрим синтаксические компоненты шаблонизатора GO.
If condition is 0 , «» , nil or empty array/slice, condition is processed as false , T1 won’t execute. Otherwise — T1 will execute.
Variations with else , else if :
if condition>> T1 else>> T0 end>> if condition1>> T1 else if condition2>> T0 end>>
One can iterate arrays, slices, maps or channels.
In the following code T1 instruction will be executed on each iteration:
range pipeline>> T1 else>> T2 end>>
Key/value variables for each iteration also can be obtained:
range $key, $value := pipeline>> $key >>: $value >> end>>
If pipeline is equivalent to true (like it is decribed in if explanation), T1 is executed, current template context is set to pipeline.
One can create template by one of following instructions:
block "name" pipeline>> T1 end>>
define "name" pipeline>> T1 end>>
Map elements, struct fields, method calls
GO templates can print data.
For example, one can print struct field or map value. Struct fields to be used in templates should be exported (started with capital letter).
Map keys could start with lowercase letter.
All of them can be chained:
One can use method calls in templates. Template method should return one value or two values and the last value should be an error . There is such method check in the sources.
type myType struct> func(m *myType) Method() string return "123" >
There are two type of function in GO templates — builtin and user defined.
Function call syntax for every function is following:
- call funcLocation arg1 arg2 — function to call a function with arguments;
- index x 1 2 3 — obtaining a slice/array/map elemtn;
- slice x 1 2 — slicing slice/array — s[1:2] ;
- len x — obtaining len of slice/array/map;
- print , printf , println — explicit printing data;
Boolean operators also work as functions:
- eq arg1 arg2 — arg1 == arg2
- ne arg1 arg2 — arg1 != arg2
- lt arg1 arg2 — arg1
- le arg1 arg2 — arg1
- gt arg1 arg2 — arg1 > arg2
- ge arg1 arg2 — arg1 >= arg2
One can define any function in GO to use it later in templates. GO-code of last function which helps to check if the iterated element is the last in list:
tempTemplate := template.New("main").Funcs( template.FuncMap "last": func(x int, a interface>) bool return x == reflect.ValueOf(a).Num()-1 >, >)
$allKeywords := .Data.Keywords >> range $k,$v := .Data.Keywords>> $v >> if ne (last $i $allKeywords) >>, end >> end >>
GO templates are using reflect package to work with any data type. For example, range sources in text/template :
func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) // . switch val.Kind() case reflect.Array, reflect.Slice: // . case reflect.Map: // . case reflect.Chan: // . >
There is logical branch for every iterated type. Same reflect approach is in the eval field inturction sources. html/template uses text/template . html/template is specifically designed to identify exactly which type html-content is processed by template (html tag’s name, attribute, tag’s content, css-content, URL). Based on this content identification there different escape solutions.