View on GitHub

sprig

Useful template functions for Go templates.

Dictionaries and Dict Functions

Sprig provides a key/value storage type called a dict (short for “dictionary”, as in Python). A dict is an unorder type.

The key to a dictionary must be a string. However, the value can be any type, even another dict or list.

Unlike lists, dicts are not immutable. The set and unset functions will modify the contents of a dictionary.

dict

Creating dictionaries is done by calling the dict function and passing it a list of pairs.

The following creates a dictionary with three items:

$myDict := dict "name1" "value1" "name2" "value2" "name3" "value 3"

get

Given a map and a key, get the value from the map.

get $myDict "name1"

The above returns "value1"

Note that if the key is not found, this operation will simply return "". No error will be generated.

set

Use set to add a new key/value pair to a dictionary.

$_ := set $myDict "name4" "value4"

Note that set returns the dictionary (a requirement of Go template functions), so you may need to trap the value as done above with the $_ assignment.

unset

Given a map and a key, delete the key from the map.

$_ := unset $myDict "name4"

As with set, this returns the dictionary.

Note that if the key is not found, this operation will simply return. No error will be generated.

hasKey

The hasKey function returns true if the given dict contains the given key.

hasKey $myDict "name1"

If the key is not found, this returns false.

pluck

The pluck function makes it possible to give one key and multiple maps, and get a list of all of the matches:

pluck "name1" $myDict $myOtherDict

The above will return a list containing every found value ([value1 otherValue1]).

If the give key is not found in a map, that map will not have an item in the list (and the length of the returned list will be less than the number of dicts in the call to pluck.

If the key is found but the value is an empty value, that value will be inserted.

A common idiom in Sprig templates is to uses pluck... | first to get the first matching key out of a collection of dictionaries.

dig

The dig function traverses a nested set of dicts, selecting keys from a list of values. It returns a default value if any of the keys are not found at the associated dict.

dig "user" "role" "humanName" "guest" $dict

Given a dict structured like

{
  user: {
    role: {
      humanName: "curator"
    }
  }
}

the above would return "curator". If the dict lacked even a user field, the result would be "guest".

Dig can be very useful in cases where you’d like to avoid guard clauses, especially since Go’s template package’s and doesn’t shortcut. For instance and a.maybeNil a.maybeNil.iNeedThis will always evaluate a.maybeNil.iNeedThis, and panic if a lacks a maybeNil field.)

dig accepts its dict argument last in order to support pipelining. For instance:

merge a b c | dig "one" "two" "three" "<missing>"

merge, mustMerge

Merge two or more dictionaries into one, giving precedence to the dest dictionary:

$newdict := merge $dest $source1 $source2

This is a deep merge operation but not a deep copy operation. Nested objects that are merged are the same instance on both dicts. If you want a deep copy along with the merge than use the deepCopy function along with merging. For example,

deepCopy $source | merge $dest

mustMerge will return an error in case of unsuccessful merge.

mergeOverwrite, mustMergeOverwrite

Merge two or more dictionaries into one, giving precedence from right to left, effectively overwriting values in the dest dictionary:

Given:

dst:
  default: default
  overwrite: me
  key: true

src:
  overwrite: overwritten
  key: false

will result in:

newdict:
  default: default
  overwrite: overwritten
  key: false
$newdict := mergeOverwrite $dest $source1 $source2

This is a deep merge operation but not a deep copy operation. Nested objects that are merged are the same instance on both dicts. If you want a deep copy along with the merge than use the deepCopy function along with merging. For example,

deepCopy $source | mergeOverwrite $dest

mustMergeOverwrite will return an error in case of unsuccessful merge.

keys

The keys function will return a list of all of the keys in one or more dict types. Since a dictionary is unordered, the keys will not be in a predictable order. They can be sorted with sortAlpha.

keys $myDict | sortAlpha

When supplying multiple dictionaries, the keys will be concatenated. Use the uniq function along with sortAlpha to get a unqiue, sorted list of keys.

keys $myDict $myOtherDict | uniq | sortAlpha

pick

The pick function selects just the given keys out of a dictionary, creating a new dict.

$new := pick $myDict "name1" "name2"

The above returns {name1: value1, name2: value2}

omit

The omit function is similar to pick, except it returns a new dict with all the keys that do not match the given keys.

$new := omit $myDict "name1" "name3"

The above returns {name2: value2}

values

The values function is similar to keys, except it returns a new list with all the values of the source dict (only one dictionary is supported).

$vals := values $myDict

The above returns list["value1", "value2", "value 3"]. Note that the values function gives no guarantees about the result ordering- if you care about this, then use sortAlpha.

deepCopy, mustDeepCopy

The deepCopy and mustDeepCopy functions takes a value and makes a deep copy of the value. This includes dicts and other structures. deepCopy panics when there is a problem while mustDeepCopy returns an error to the template system when there is an error.

dict "a" 1 "b" 2 | deepCopy

A Note on Dict Internals

A dict is implemented in Go as a map[string]interface{}. Go developers can pass map[string]interface{} values into the context to make them available to templates as dicts.