Maîtriser le moteur de Templates GO

Maîtriser le moteur de Templates GO

De plus en plus de logiciels sont codés en langage GO, que ce soit Kubernetes, Docker, Helm, Grafana etc... Maîtriser son moteur de templates est donc un réel gage de qualité.
Il faut savoir que le langage GO embarque un moteur de templates très puissant, et souvent utile pour les logiciels précédemment cités. Regardons comment manipuler le moteur de templates GO pour générer un JSON.

Parser un JSON

Il existe énormément de cas d'usage nous amenant à manipuler le moteur de templates du langage GO. Un cas courant est celui de la commande docker inspect utilisée avec l'argument -f.

Voici un exemple avec la commande docker inspect qui affiche uniquement l'adresse IP du conteneur :

docker inspect --format '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' NOM DU CONTENEUR

La fonction range du moteur de templates Go permet d'itérer sur une séquence de données. On peut la considérer comme l'équivalent d'une boucle for.

À l'intérieur de la boucle range, vous pouvez accéder à chaque élément de la séquence avec le point ..

Générer un JSON

Dans certains cas, il est nécessaire de générer un JSON à partir d'un template GO.
Par exemple avec l'outil Trivy qui permet de scanner les CVE d'une machine, il est possible de formater la sortie directement en JSON.

Sauf que le JSON qui est généré contient beaucoup d'informations qui ne sont pas forcément utiles, cela rend également le fichier très long, et réduit les performances lorsqu'il faut le parser.
C'est pour cela que générer un JSON avec un template GO peut s'avérer très intéressant afin de ne garder uniquement les informations qui sont pertinentes.

Pour ce faire, il faut utiliser la fonction toJson et l'afficher avec printf. Voici un exemple de template GO :

{{- range . }}{{- range .MyKey }}
{{- $json := dict "Key1" .Myvalue1 "Key2" .Myvalue2 | toJson }}
{{- printf "%s\n" $json }}
{{- end }}{{- end }}
💡
Remplacez Key1et Myvalue1 par vos clés et valeurs JSON.

Ce template GO vient générer un JSON qui ressemble à ceci :

{"Key1": Myvalue1,"Key2": Myvalue2}

La comparaison

Il est possible de comparer des éléments dans un template GO, pour notamment vérifier si deux chaînes de caractères sont identiques, vérifier un booléen etc...

Certains opérateurs vont vous paraître familier car ils ressemblent beaucoup au langage Bash et au moteur de templates Jinja2.

Utilisons les opérateurs eq et not pour nos comparaisons :

{{ if eq .Car "BMW" }}
	La voiture est une BMW.
{{ else if not eq .Car "Mercedes" }}
	La voiture est ni une BMW ni une Mercedes
{{ else }}
	La voiture est une Mercedes.
{{ end }}

Dans cet exemple, nous testons avec un if si la clé .Car est égale à la valeur "BMW". Si c'est le cas, le template GO affiche "La voitures est une BMW.".

Sinon, le test else if vérifie si la clé .Car n'est pas égale à la chaîne "Mercedes". Si c'est le cas, le template GO affiche "La voiture est ni une BMW ni une Mercedes".

Sinon, dans le else nous affichons "La voiture est une Mercedes.".

Il est possible d'utiliser la négation avec l'opérateur not comme dans cet exemple :

{{ $car := "Audi" }}
{{ if not (eq $car "BMW") }}
    Ma voiture est {{ $car }}!
{{ end }}

Les listes

Pour déclarer une liste dans un template GO, il faut utiliser la fonction slice. Voici un exemple avec la déclaration d'une variable nommée car qui stocke cette liste :

{{ $car := slice "BMW" "Mercedes" "Audi" }}

Pour itérer dans cette liste slice, nous allons utiliser la fonction range comme ceci :

{{ range $index, $element := $car }}
    L'élément numéro {{ $index }} est {{ $element }}
{{ end }}

Les dictionnaires

Il est possible d'utiliser les dictionnaires dans un template GO afin d'y stocker clés et valeurs. Pour ce faire, il faut utiliser la fonction dict comme dans l'exemple suivant :

{{ $car := dict "Marque" "BMW" "Classe" "Berline" "Année" 2022 }}

Il est possible d'accéder aux valeurs de ce dictionnaire de cette manière :

{{$car.Marque}}    // affiche "BMW"
{{$car.Classe}}    // affiche "Berline"
{{$car.Année}}     // affiche 2022

Conclusion

Nous avons pu voir dans cet article que le moteur de templates du langage GO est très puissant, et sera amené à être de plus en plus utilisé avec la démocratisation du langage GO.

A titre de comparaison avec le moteur de templates Jinja2, les fonctions comme toJson, toYaml, block et bien d'autres fonctions ne sont pas présentes en Jinja2. Cela rend la manipulation et la génération de fichiers plus simple en GO.