Formater une chaîne Go sans imprimer ?
Chaînes de caractères simples
Pour les chaînes de caractères « simples » (typiquement ce qui tient dans une ligne), la solution la plus simple consiste à utiliser fmt.Sprintf()
et ses amis (fmt.Sprint()
, fmt.Sprintln()
). Elles sont analogues aux fonctions sans la lettre de départ S
, mais ces variantes de Sxxx()
renvoient le résultat sous forme de string
au lieu de les imprimer sur la sortie standard.
Par exemple:
s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)
La variable s
sera initialisée avec la valeur:
Hi, my name is Bob and I'm 23 years old.
Tip : Si vous voulez juste concaténer des valeurs de différents types, vous n’aurez peut-être pas automatiquement besoin d’utiliser Sprintf()
(qui nécessite une chaîne de format) car Sprint()
fait exactement cela. Voyez cet exemple :
i := 23s := fmt.Sprint("") // s will be ""
Pour concaténer uniquement des string
, vous pouvez également utiliser strings.Join()
où vous pouvez spécifier un séparateur personnalisé string
(à placer entre les chaînes à joindre).
Essayez-les sur le terrain de jeu Go.
Chaînes complexes (documents)
Si la chaîne que vous essayez de créer est plus complexe (par exemple un message électronique de plusieurs lignes), fmt.Sprintf()
devient moins lisible et moins efficace (surtout si vous devez le faire plusieurs fois).
Pour cela, la bibliothèque standard fournit les packages text/template
et html/template
. Ces paquets mettent en œuvre des modèles pilotés par les données pour générer une sortie textuelle. html/template
est destiné à générer une sortie HTML sécurisée contre l’injection de code. Il fournit la même interface que le paquet text/template
et devrait être utilisé à la place de text/template
chaque fois que la sortie est du HTML.
L’utilisation des paquets template
nécessite essentiellement de fournir un modèle statique sous la forme d’une valeur string
(qui peut provenir d’un fichier, auquel cas vous ne fournissez que le nom du fichier) qui peut contenir du texte statique, et des actions qui sont traitées et exécutées lorsque le moteur traite le modèle et génère la sortie.
Vous pouvez fournir des paramètres qui sont inclus/substitués dans le modèle statique et qui peuvent contrôler le processus de génération de la sortie. La forme typique de tels paramètres sont des valeurs struct
s et map
qui peuvent être imbriquées.
Exemple:
Par exemple, disons que vous voulez générer des messages électroniques qui ressemblent à ceci:
Hi !Your account is ready, your user name is: You have the following roles assigned:, , ...
Pour générer des corps de messages électroniques comme ceci, vous pourriez utiliser le modèle statique suivant :
const emailTmpl = `Hi {{.Name}}!Your account is ready, your user name is: {{.UserName}}You have the following roles assigned:{{range $i, $r := .Roles}}{{if $i}}, {{end}}{{.}}{{end}}`
Et fournir des données comme ceci pour l’exécuter:
data := mapinterface{}{ "Name": "Bob", "UserName": "bob92", "Roles": string{"dbteam", "uiteam", "tester"},}
Normalement la sortie des modèles est écrite dans un io.Writer
, donc si vous voulez le résultat comme un string
, créez et écrivez dans un bytes.Buffer
(qui implémente io.Writer
). Exécutez le modèle et obtenez le résultat sous forme de string
:
t := template.Must(template.New("email").Parse(emailTmpl))buf := &bytes.Buffer{}if err := t.Execute(buf, data); err != nil { panic(err)}s := buf.String()
Cela donnera la sortie attendue:
Hi Bob!Your account is ready, your user name is: bob92You have the following roles assigned:dbteam, uiteam, tester
Essayez-le sur le Playground de Go.
Notez également que depuis Go 1.10, une alternative plus récente, plus rapide et plus spécialisée est disponible pour bytes.Buffer
qui est : strings.Builder
. L’utilisation est très similaire:
builder := &strings.Builder{}if err := t.Execute(builder, data); err != nil { panic(err)}s := builder.String()
Essayez celle-ci sur le Go Playground.
Note : vous pouvez également afficher le résultat de l’exécution d’un modèle si vous fournissez os.Stdout
comme cible (qui implémente également io.Writer
):
t := template.Must(template.New("email").Parse(emailTmpl))if err := t.Execute(os.Stdout, data); err != nil { panic(err)}
Cela écrira le résultat directement dans os.Stdout
. Essayez ceci sur le terrain de jeu Go.