Syntax
Gomplate uses the syntax understood by the Go language’s text/template
package. This page documents some of that syntax, but see the language docs
for full details.
The basics
Templates are just regular text, with special actions delimited by {{
and }}
markers. Consider the following template:
Hello, {{ print "World" }}!
If you render this template, it will produce the following output:
Hello, World!
This is obviously a contrived example, and you would likely never see this in
real life, but this conveys the basics, which is that actions are delimited
by {{
and }}
, and are replaced with their output (if any) when the template
is rendered.
Multi-line templates
By default, every line containing an action will render a newline. For example, the action block below:
{{ range coll.Slice "Foo" "bar" "baz" }}
Hello, {{ . }}!
{{ end }}
will produce the output below:
Hello, Foo!
Hello, bar!
Hello, baz!
This might not be desirable.
You can use Golang template syntax to fix this. Leading newlines (i.e. newlines that come before the action) can be suppressed by placing a minus sign in front of the first set of delimiters ({{
). Putting the minus sign behind the trailing set of delimiters (}}
) will suppress the newline after the action. You can do both to suppress newlines entirely on that line.
Placing the minus sign within the context (i.e. inside of {{.}}
) has no effect.
Here are a few examples.
Suppressing leading newlines
{{- range coll.Slice "Foo" "bar" "baz" }}
Hello, {{ . }}!
{{- end }}
will produce this:
Hello, Foo!
Hello, bar!
Hello, baz!
Suppressing trailling newlines
This code:
{{ range coll.Slice "Foo" "bar" "baz" -}}
Hello, {{ . }}!
{{ end -}}
yields this:
Hello, Foo!
Hello, bar!
Hello, baz!
Suppressing newlines altogether
This code:
{{- range coll.Slice "Foo" "bar" "baz" -}}
Hello, {{ . }}!
{{- end -}}
Produces:
Hello, Foo!Hello, bar!Hello, baz!
Variables
The result of an action can be assigned to a variable, which is denoted by a
leading $
character, followed by an alphanumeric string. For example:
{{ $w := "world" }}
Hello, {{ print $w }}!
Goodbye, {{ print $w }}.
this will render as:
Hello, world!
Goodbye, world.
Variables are declared with :=
, and can be redefined with =
:
{{ $w := "hello" }}
{{ $w = "goodbye" }}
Variable scope
A variable’s scope extends to the end
action of the control structure (if
,
with
, or range
) in which it is declared, or to the end of the template if
there is no such control structure.
In other words, if a variable is initialized inside an if
or else
block,
it cannot be referenced outside that block.
This template will error with undefined variable "$w"
since $w
is only
declared within if
/else
blocks:
{{ if 1 }}
{{ $w := "world" }}
{{ else }}
{{ $w := "earth" }}
{{ end }}
Hello, {{ print $w }}!
Goodbye, {{ print $w }}.
One way to approach this is to declare the variable first to an empty value:
{{ $w := "" }}
{{ if 1 }}
{{ $w = "world" }}
{{ else }}
{{ $w = "earth" }}
{{ end -}}
Hello, {{ print $w }}!
Goodbye, {{ print $w }}.
Indexing arrays and maps
Occasionally, multi-dimensional data such as arrays (lists, slices) and maps (dictionaries) are used in templates, sometimes through the use of data sources. Accessing values within these data can be done in a few ways which bear clarifying.
Arrays
Arrays are always numerically-indexed, and individual values can be accessed with the index
built-in function:
{{ index $array 0 }}
To visit each value, you can loop through an array with range
:
{{ range $array }}
do something with {{ . }}...
{{ end }}
If you need to keep track of the index number, you can declare two variables, separated by a comma:
{{ range $index, $element := $array }}
do something with {{ $element }}, which is number {{ $index }}
{{ end }}
Maps
For maps, accessing values can be done with the .
operator. Given a map $map
with a key foo
, you could access it like:
{{ $map.foo }}
However, this kind of access is limited to keys which are strings and contain
only characters in the set (a
-z
,A
-Z
,_
,1
-9
), and which do not begin
with a number. If the key doesn’t conform to these rules, you can use the index
built-in function instead:
{{ index $map "foo-bar" }}
index
also supports nested keys and can be combined with other functions as such:
{{ index $map "foo" (env.Getenv "BAR") "baz" ... }}
Note: while index
can be used to access awkwardly-named values in maps,
it behaves differently than the .
operator. If the key doesn’t exist, index
will simply not return a value, while .
will error.
And, similar to arrays, you can loop through a map with the range
:
{{ range $map }}
The value is {{ . }}
{{ end }}
Or if you need keys as well:
{{ range $key, $value := $map }}
{{ $key }}'s value is: {{ $value }}
{{ end }}
Functions
Almost all of gomplate’s utility is provided as functions. These are key
words (like print
in the previous examples) that perform some action.
See the functions documentation for more information.
The Context
Go templates are always executed with a context. You can reference the context
with the .
(period) character, and you can set the context in a block with the
with
action. Like so:
$ gomplate -i '{{ with "foo" }}The context is {{ . }}{{ end }}'
The context is foo
Templates rendered by gomplate always have a default context. You can populate
the default context from data sources with the --context
/c
flag. The special context item .Env
is available for referencing the
system’s environment variables.
Note: The initial context (.
) is always available as the variable $
,
so the initial context is always available, even when shadowed with range
or with
blocks:
$ echo '{"bar":"baz"}' | gomplate -c .=stdin:///in.json -i 'context is: {{ . }}
{{ with "foo" }}now context is {{ . }}
but the original context is still {{ $ }}
{{ end }}'
context is: map[bar:baz]
now context is foo
but the original context is still map[bar:baz]
Nested templates
Gomplate supports nested templates, using Go’s template
action. These can be
defined in-line with the define
action, or external data can be used with the
--template
/-t
flag.
Note that nested templates do not have access to gomplate’s default
context (though it can be explicitly provided to the template
action).
In-line templates
To define a nested template in-line, you can use the define
action.
{{ define "T1" -}}
Hello {{ . }}!
{{- end -}}
{{ template "T1" "World" }}
{{ template "T1" }}
{{ template "T1" "everybody" }}
This renders as:
Hello World!
Hello <no value>!
Hello everybody!
External templates
To define a nested template from an external source such as a file, use the
--template
/-t
flag.
hello.t:
Hello {{ . }}!
$ gomplate -t hello=hello.t -i '{{ template "hello" "World" }} {{ template "hello" .Env.USER }}'
Hello World! Hello hairyhenderson!
.Env
You can easily access environment variables with .Env
, but there’s a catch:
if you try to reference an environment variable that doesn’t exist, parsing
will fail and gomplate
will exit with an error condition.
For example:
$ gomplate -i 'the user is {{ .Env.USER }}'
the user is hairyhenderson
$ gomplate -i 'this will fail: {{ .Env.BOGUS }}'
this will fail: template: <arg>:1:23: executing "<arg>" at <.Env.BOGUS>: map has no entry for key "BOGUS"
Sometimes, this behaviour is desired; if the output is unusable without certain strings, this is a sure way to know that variables are missing!
If you want different behaviour, try getenv
.