web-dev-qa-db-fra.com

Formater une chaîne Go sans imprimer?

Existe-t-il un moyen simple de formater une chaîne dans Go sans l’imprimer?

Je peux faire:

bar := "bar"
fmt.Printf("foo: %s", bar)

Mais je veux que la chaîne formatée soit renvoyée plutôt qu'imprimée afin que je puisse la manipuler davantage.

Je pourrais aussi faire quelque chose comme:

s := "foo: " + bar

Mais cela devient difficile à lire lorsque la chaîne de format est complexe et fastidieux quand une ou plusieurs parties ne sont pas des chaînes et doivent être converties en premier, comme

i := 25
s := "foo: " + strconv.Itoa(i)

Y a-t-il un moyen plus simple de faire cela?

325
Carnegie

Sprintf est ce que vous recherchez.

Exemple

fmt.Sprintf("foo: %s", bar)

Vous pouvez également le voir en cours d’utilisation dans le Exemple d’erreurs dans le cadre de "A Tour of Go".

return fmt.Sprintf("at %v, %s", e.When, e.What)
403
Sonia

1. Chaînes simples

Pour les chaînes "simples" (typiquement ce qui rentre dans une ligne), la solution la plus simple consiste à utiliser fmt.Sprintf() et amis ( fmt.Sprint() , fmt.Sprintln() ). Celles-ci sont analogues aux fonctions sans la lettre S de débutant, mais ces variantes Sxxx() renvoient le résultat sous la forme 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.
_

Astuce: Si vous voulez simplement concaténer des valeurs de types différents, vous n’aurez peut-être pas besoin d’utiliser automatiquement Sprintf() (qui nécessite une chaîne de format), comme Sprint() le fait exactement. cette. Voir cet exemple:

_i := 23
s := fmt.Sprint("[age:", i, "]") // s will be "[age:23]"
_

Pour concaténer uniquement strings, 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 Go Playground .

2. Chaînes complexes (documents)

Si la chaîne que vous essayez de créer est plus complexe (par exemple, un message électronique comportant 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 packages implémentent des modèles basés sur 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 package _text/template_ et doit être utilisé à la place de _text/template_ lorsque la sortie est au format HTML.

L'utilisation des packages template nécessite généralement de fournir un modèle statique sous la forme d'une valeur string (pouvant provenir d'un fichier, auquel cas vous ne fournissez que le nom du fichier) pouvant contenir du texte statique. , et les 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 inclus/substitués dans le modèle statique et pouvant contrôler le processus de génération de sortie. La forme typique de tels paramètres est les valeurs structs et map qui peuvent être imbriquées.

Exemple:

Par exemple, supposons que vous souhaitiez générer des courriers électroniques ressemblant à ceci:

_Hi [name]!

Your account is ready, your user name is: [user-name]

You have the following roles assigned:
[role#1], [role#2], ... [role#n]
_

Pour générer un tel corps de message, vous pouvez 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 ne $i 0}}, {{end}}{{.}}{{end}}
`
_

Et fournissez des données comme celle-ci pour l’exécuter:

_data := map[string]interface{}{
    "Name":     "Bob",
    "UserName": "bob92",
    "Roles":    []string{"dbteam", "uiteam", "tester"},
}
_

Normalement, les modèles de sortie sont écrits dans un io.Writer , donc si vous voulez obtenir le résultat sous la forme string, créez-le et écrivez dans un bytes.Buffer (qui implémente _io.Writer_). Exécuter le modèle et obtenir le résultat sous la forme 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 le résultat attendu:

_Hi Bob!

Your account is ready, your user name is: bob92

You have the following roles assigned:
dbteam, uiteam, tester
_

Essayez-le sur le Go Playground .

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 celui-ci sur le Go Playground .

Remarque: vous pouvez également afficher le résultat d'une exécution de modèle si vous spécifiez _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)
}
_

Ceci écrira le résultat directement dans _os.Stdout_. Essayez ceci sur le Go Playground .

175
icza

Dans votre cas, vous devez utiliser Sprintf () pour la chaîne de format.

func Sprintf(format string, a ...interface{}) string

Sprintf se formate selon un spécificateur de format et renvoie la chaîne résultante.

s := fmt.Sprintf("Good Morning, This is %s and I'm living here from last %d years ", "John", 20)

Votre sortie sera:

Bonjour, voici John et je vis ici depuis 20 ans.

1
Kabeer Shaikh

La fonction fmt.SprintF renvoie une chaîne et vous pouvez la formater de la même manière que vous auriez avec fmt.PrintF

0
Mo-Gang