Eine Go-Zeichenkette formatieren ohne zu drucken?

Jun 28, 2021
admin

Einfache Zeichenketten

Für „einfache“ Zeichenketten (typischerweise das, was in eine Zeile passt) ist die einfachste Lösung die Verwendung von fmt.Sprintf() und Freunden (fmt.Sprint(), fmt.Sprintln()). Diese sind analog zu den Funktionen ohne den Anfangsbuchstaben S, aber diese Sxxx()-Varianten geben das Ergebnis als string zurück, anstatt es auf der Standardausgabe auszugeben.

Beispiel:

s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)

Die Variable s wird mit dem Wert initialisiert:

Hi, my name is Bob and I'm 23 years old.

Tipp: Wenn Sie nur Werte verschiedener Typen verketten wollen, müssen Sie nicht automatisch Sprintf() (das einen Formatstring erfordert) verwenden, da Sprint() genau das tut. Siehe dieses Beispiel:

i := 23s := fmt.Sprint("") // s will be ""

Wenn Sie nur strings verketten wollen, können Sie auch strings.Join() verwenden, wo Sie ein benutzerdefiniertes Trennzeichen string (das zwischen den zu verbindenden Strings platziert wird) angeben können.

Probieren Sie dies auf dem Go Playground.

Komplexe Zeichenketten (Dokumente)

Wenn die Zeichenkette, die Sie zu erstellen versuchen, komplexer ist (z.B. eine mehrzeilige E-Mail), fmt.Sprintf() wird sie weniger lesbar und weniger effizient (besonders, wenn Sie dies viele Male tun müssen).

Dafür bietet die Standardbibliothek die Pakete text/template und html/template. Diese Pakete implementieren datengesteuerte Vorlagen zur Erzeugung von Textausgaben. html/template dient der Erzeugung von HTML-Ausgaben, die gegen Code-Injection sicher sind. Es bietet die gleiche Schnittstelle wie das Paket text/template und sollte anstelle von text/template verwendet werden, wenn die Ausgabe HTML ist.

Die Verwendung der template-Pakete erfordert im Wesentlichen, dass Sie eine statische Vorlage in Form eines string-Wertes bereitstellen (der aus einer Datei stammen kann, in welchem Fall Sie nur den Dateinamen bereitstellen), der statischen Text enthalten kann, und Aktionen, die verarbeitet und ausgeführt werden, wenn die Engine die Vorlage verarbeitet und die Ausgabe erzeugt.

Sie können Parameter angeben, die in der statischen Vorlage enthalten/ersetzt werden und die den Prozess der Ausgabeerzeugung steuern können. Typische Formen solcher Parameter sind structs und map-Werte, die verschachtelt sein können.

Beispiel:

Angenommen, Sie möchten E-Mail-Nachrichten generieren, die wie folgt aussehen:

Hi !Your account is ready, your user name is: You have the following roles assigned:, , ... 

Um E-Mail-Nachrichtenkörper wie diesen zu generieren, könnten Sie die folgende statische Vorlage verwenden:

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}}`

Und Daten wie diese für die Ausführung bereitstellen:

data := mapinterface{}{ "Name": "Bob", "UserName": "bob92", "Roles": string{"dbteam", "uiteam", "tester"},}

Normalerweise wird die Ausgabe von Vorlagen in ein io.Writer geschrieben. Wenn Sie also das Ergebnis als string haben möchten, erstellen Sie ein bytes.Buffer (das io.Writer implementiert) und schreiben Sie es in dieses. Das Ausführen der Vorlage und das Erhalten des Ergebnisses als 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()

Dies führt zu der erwarteten Ausgabe:

Hi Bob!Your account is ready, your user name is: bob92You have the following roles assigned:dbteam, uiteam, tester

Versuchen Sie es auf dem Go Playground.

Beachten Sie auch, dass seit Go 1.10 eine neuere, schnellere, spezialisiertere Alternative zu bytes.Buffer verfügbar ist, nämlich strings.Builder. Die Verwendung ist sehr ähnlich:

builder := &strings.Builder{}if err := t.Execute(builder, data); err != nil { panic(err)}s := builder.String()

Versuchen Sie dies auf dem Go Playground.

Hinweis: Sie können auch das Ergebnis einer Template-Ausführung anzeigen, wenn Sie os.Stdout als Ziel angeben (das auch io.Writer implementiert):

t := template.Must(template.New("email").Parse(emailTmpl))if err := t.Execute(os.Stdout, data); err != nil { panic(err)}

Dies schreibt das Ergebnis direkt nach os.Stdout. Probieren Sie dies auf dem Go Playground aus.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.