Templates Go - Maîtrisez `text/template` et `html/template`

Léon Weiss .

13 mars 2026

Un mignon personnage bleu, entouré d'accolades, illustre la création d'un blog avec Go Templates.

Le système de templates de Go, souvent appelé go template, sert à séparer proprement les données et la présentation sans alourdir un backend. Je m’en sers surtout quand je veux générer du HTML, du texte, un email ou un fichier de configuration avec une logique lisible et peu de dépendances. Dans cet article, je vais expliquer comment il fonctionne, quand choisir `text/template` ou `html/template`, comment structurer des templates maintenables, et quels pièges j’évite systématiquement en revue de code.

Ce moteur transforme des données en texte lisible, sûr et facile à maintenir

  • `text/template` sert au texte brut, tandis que `html/template` ajoute un échappement contextuel pour le HTML.
  • La syntaxe repose sur `{{ ... }}`, le point `.` pour les données courantes et les pipelines pour garder les actions courtes.
  • Pour une page web, je recommande presque toujours `html/template`; pour les emails, les exports ou la génération de fichiers, `text/template` reste très adapté.
  • Les fonctions personnalisées doivent être enregistrées avant le parsing, sinon elles ne sont pas disponibles au moment de l’analyse.
  • `missingkey=error` est un réglage simple qui évite beaucoup d’erreurs silencieuses en développement et en production.

Ce que fait vraiment le moteur de templates de Go

Le point clé est simple: un template Go n’est pas un mini-framework de présentation, c’est un moteur d’assemblage entre une structure de données et une sortie finale. Le texte hors balises est copié tel quel, et tout ce qui se trouve entre `{{` et `}}` devient une action qui lit des champs, appelle une fonction, exécute une condition ou parcourt une collection. La documentation de Go insiste sur ce découplage: le template reçoit des données, puis il navigue dans la structure via le point `.`.

Dans la pratique, je l’utilise pour trois cas très différents: un site web généré côté serveur, un email transactionnel, ou un fichier texte à produire automatiquement. Le même mécanisme reste utile tant que la sortie finale est du texte et que la logique métier reste dans le code Go, pas dans le template. C’est précisément ce qui rend l’outil sobre et durable. Une fois ce modèle en tête, la syntaxe devient beaucoup moins intimidante.

Un adorable personnage bleu, inspiré par le logo Go, est entouré d'accolades, symbolisant la création d'un blog avec Go Templates.

Comprendre la syntaxe sans se perdre

Le langage de template est compact, mais il faut assimiler quelques repères: `.` pour les données courantes, `$` pour une variable, `if` pour une condition, `range` pour itérer, `with` pour réorienter le point courant, et les pipelines pour chaîner les opérations de façon lisible. Je conseille de commencer par ces briques avant d’ajouter des fonctions personnalisées, parce qu’elles couvrent déjà une grande partie des besoins quotidiens.

Construction Rôle Quand je l’utilise
{{.Title}} Lit un champ ou une clé dans les données. Pour afficher une valeur simple, sans logique supplémentaire.
{{if .Published}}...{{end}} Affiche un bloc seulement si la condition est vraie. Pour masquer une section vide ou un état non prêt.
{{range .Tags}}...{{end}} Parcourt une tranche, une liste ou une map. Pour générer des items de menu, des tags ou des lignes de tableau.
{{with .Author}}...{{end}} Change le point courant pour simplifier l’accès aux champs. Quand une sous-structure est présente mais facultative.
{{printf "%s" .Body}} Appelle une fonction ou un pipeline. Pour formater une valeur sans encombrer le Go côté serveur.

Ce que je trouve le plus utile, c’est la lisibilité du pipeline. Au lieu d’écrire de la logique imbriquée, on peut enchaîner des étapes courtes et explicites. Un template comme {{.Title | printf "%q"}} dit immédiatement ce qu’il fait: il récupère la valeur, puis la formate. C’est simple, mais très efficace quand le projet grandit. Reste à choisir le bon package selon la sortie visée.

Choisir entre texte brut et HTML sécurisé

Go fournit deux paquets proches, mais leur objectif n’est pas le même. text/template rend du texte brut et n’ajoute aucun échappement automatique; html/template reprend la même API, mais ajoute un échappement contextuel pensé pour le HTML. Pour toute page web, la règle que je garde est presque binaire: si la sortie est du HTML, j’utilise html/template; sinon je pars sur text/template.

Critère text/template html/template
Sortie cible Texte, emails, fichiers, logs, Markdown, génération de code. HTML servi à un navigateur.
Échappement Aucun échappement automatique. Échappement contextuel selon HTML, attribut, URL, CSS ou JS.
Risque principal Injection si on l’emploie pour produire du HTML sans protection. Mauvaise confiance dans des données ou des types “safes”.
Cas typique Mail transactionnel, export texte, fichier de config. Page serveur, fragment de vue, formulaire, widget HTML.
Mon réflexe Par défaut pour tout ce qui n’est pas du HTML. Dès que le navigateur est le consommateur final.

Le vrai intérêt de html/template n’est pas seulement l’échappement du texte. Il comprend aussi les contextes HTML, JS, CSS et URI, donc il adapte la sortie à l’endroit où la donnée apparaît. C’est pratique, mais je ne traite jamais ça comme un remplaçant de la validation serveur: un champ mal formé reste un problème métier, même s’il est correctement encodé à l’affichage. Le vrai sujet devient alors l’organisation du code.

Organiser des templates maintenables dans un vrai projet

Quand un projet grossit, le sujet n’est plus la syntaxe. Le vrai enjeu devient le chargement, le nommage et la réutilisation. Je préfère charger tous les templates au démarrage, les nommer clairement, puis rendre des sous-templates avec ExecuteTemplate plutôt que de concaténer du HTML à la main dans les handlers.

  • ParseFiles convient quand vous avez quelques fichiers locaux et un chargement direct.
  • ParseGlob devient utile quand vous organisez plusieurs vues par motif de fichiers.
  • ParseFS est très pratique si vous embarquez les templates avec embed pour un déploiement autonome.
  • ExecuteTemplate permet de cibler un layout ou un fragment nommé sans ambiguïté.
  • Funcs doit être appelé avant le parsing si vous voulez utiliser des helpers comme upper, truncate ou un formateur de devise.
//go:embed templates/*.html
var templatesFS embed.FS

var tpl = template.Must(
    template.New("base").
        Funcs(template.FuncMap{
            "upper": strings.ToUpper,
        }).
        Option("missingkey=error").
        ParseFS(templatesFS, "templates/*.html"),
)
{{define "base"}}


  
    {{template "content" .}}
  

{{end}}

{{define "content"}}

{{.Title}}

{{.Body}}

{{end}}

Cette structure évite la duplication et garde le rendu lisible. Elle a aussi un autre avantage: on peut tester plus facilement les layouts, les blocs de contenu et les helpers sans relire du HTML généré à la main dans un handler. Même bien structurés, les templates ont pourtant des pièges qu’il vaut mieux verrouiller tôt.

Les pièges qui ressortent en production

La plupart des bugs que je vois autour des templates ne viennent pas de la syntaxe elle-même, mais de détails d’intégration. Le premier est silencieux: une clé manquante dans une map ou une structure affiche parfois ou une valeur vide au lieu de casser franchement. En développement et en test, je préfère donc missingkey=error, parce qu’il transforme un oubli en erreur visible.
Symptôme Cause probable Réflexe utile
dans le rendu Champ absent dans les données. Activer missingkey=error pendant le dev et les tests.
HTML cassé ou non protégé Mauvais package ou mauvais contexte d’usage. Utiliser html/template pour toute sortie HTML.
Fonction introuvable Funcs appelé après le parsing. Enregistrer les helpers avant Parse.
Erreur ignorée Parse ou Execute non vérifié. Traiter chaque retour d’erreur explicitement.
Rendu partiel Une erreur est survenue après le début de l’écriture. Ne pas supposer qu’un échec ne produit rien.

Le second piège est plus architectural: vouloir faire porter au template trop de logique. Je garde les boucles, les conditions simples et le formatage léger, mais je laisse la transformation métier au code Go. La documentation de Go rappelle aussi un point important: le moteur suppose les auteurs de templates dignes de confiance, alors que les données passées à l’exécution ne le sont pas forcément. Autrement dit, je n’ouvre jamais la porte à des templates modifiables par des utilisateurs non fiables, et je n’emploie les types “sûrs” comme template.HTML ou template.JS qu’avec un contenu réellement maîtrisé. À ce stade, la question n’est plus seulement technique, elle devient architecturale.

Le niveau d’abstraction que je recommande pour un backend Go durable

Dans un backend classique, j’utilise les templates tant que l’interface reste surtout déclarative: pages serveur, mails, PDF simple, exports textuels. Dès que l’écran devient très interactif, avec état client, interactions riches et composants réutilisables complexes, je bascule plutôt vers une séparation plus nette entre API Go et frontend dédié. Les templates Go restent alors excellents pour la couche de rendu, mais ils ne doivent pas porter tout le poids du produit.

  • Je prépare les données côté Go avant de les envoyer au template, au lieu de disperser des calculs dans le HTML.
  • Je centralise le chargement des fichiers au démarrage pour détecter les erreurs tôt.
  • Je garde les helpers petits, purs et prévisibles, sinon ils deviennent une source de dette silencieuse.
  • Je teste les templates importants avec des cas réels, surtout ceux qui touchent la sécurité ou les parcours critiques.
  • J’utilise l’embarquement des fichiers quand je veux un déploiement simple et reproductible.
La bonne approche consiste à garder les templates courts, les fonctions simples, les données préparées côté Go et l’échappement géré par le bon package. C’est cette discipline qui fait des templates Go un outil fiable, pas un compromis bricolé.

Questions fréquentes

`text/template` génère du texte brut sans échappement automatique, idéal pour les emails ou fichiers de configuration. `html/template` inclut un échappement contextuel pour le HTML, protégeant contre les injections XSS et assurant la sécurité des pages web.
Il est recommandé d'utiliser `missingkey=error` pendant le développement et les tests. Ce réglage transforme les champs manquants en erreurs visibles au lieu d'afficher silencieusement ``, ce qui aide à détecter et corriger les problèmes plus tôt.
Chargez tous les templates au démarrage avec `ParseFS` (si embarqués) ou `ParseGlob`, nommez-les clairement, et utilisez `ExecuteTemplate` pour rendre des sous-templates. Enregistrez les fonctions personnalisées (`Funcs`) avant le parsing pour une meilleure maintenabilité.
Les templates Go sont excellents pour les pages serveur, emails ou exports. Pour des interfaces très interactives avec un état client complexe, il est souvent préférable de séparer l'API Go d'un frontend dédié, utilisant les templates Go pour la couche de rendu initiale.

Évaluer l'article

Moyenne: 0.0 / 5 · 0 évaluations

Tags

go template go template text/template html/template comment utiliser go template
Autor Léon Weiss
Léon Weiss
Je m'appelle Léon Weiss et j'ai huit ans d'expérience dans le développement web, avec un accent particulier sur JavaScript, le backend, NoSQL et la sécurité. Mon parcours dans ce domaine a commencé par une curiosité insatiable pour la technologie et comment elle façonne notre quotidien. J'aime explorer les défis techniques et aider les lecteurs à comprendre des concepts souvent perçus comme complexes. J'écris principalement sur des sujets liés à la sécurité des applications web et à l'optimisation des bases de données NoSQL, en m'efforçant de rendre ces informations accessibles et pratiques. Je m'engage à fournir des contenus utiles, précis et à jour, en vérifiant mes sources et en comparant les informations pour offrir une perspective claire. Mon objectif est de simplifier des sujets ardus et de suivre les tendances actuelles, afin d'aider mes lecteurs à naviguer dans le paysage en constante évolution du développement web.

Commentaires (0)

Ajouter un commentaire