Formatera en Go-sträng utan att skriva ut den?
Enkla strängar
För ”enkla” strängar (typiskt vad som ryms på en rad) är den enklaste lösningen att använda fmt.Sprintf()
och vänner (fmt.Sprint()
, fmt.Sprintln()
). Dessa är analoga med funktionerna utan startbokstaven S
, men dessa Sxxx()
-varianter returnerar resultatet som en string
i stället för att skriva ut dem till standardutgången.
Till exempel:
s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)
Variabeln s
kommer att initialiseras med värdet:
Hi, my name is Bob and I'm 23 years old.
Tip: Om du bara vill sammanfoga värden av olika typer behöver du kanske inte automatiskt använda Sprintf()
(som kräver en formatsträng) eftersom Sprint()
gör just detta. Se det här exemplet:
i := 23s := fmt.Sprint("") // s will be ""
För att sammanfoga endast string
s kan du också använda strings.Join()
där du kan ange en egen separator string
(som ska placeras mellan de strängar som ska sammanfogas).
Prova dessa på Go Playground.
Komplexa strängar (dokument)
Om strängen du försöker skapa är mer komplex (t.ex. ett e-postmeddelande med flera rader) blir fmt.Sprintf()
mindre läsbar och mindre effektiv (särskilt om du måste göra detta många gånger).
För detta tillhandahåller standardbiblioteket paketen text/template
och html/template
. Dessa paket implementerar datadrivna mallar för att generera textutdata. html/template
är till för att generera HTML-utdata som är säkra mot kodinjektion. Det tillhandahåller samma gränssnitt som paket text/template
och bör användas i stället för text/template
närhelst utmatningen är HTML.
Användning av template
-paketen kräver i princip att du tillhandahåller en statisk mall i form av ett string
-värde (som kan härstamma från en fil, i vilket fall du bara tillhandahåller filnamnet) som kan innehålla statisk text, och åtgärder som bearbetas och exekveras när motorn behandlar mallen och genererar utmatningen.
Du kan tillhandahålla parametrar som ingår/ersätts i den statiska mallen och som kan styra processen för generering av utdata. Typiska former av sådana parametrar är struct
s och map
värden som kan vara nästlade.
Exempel:
Till exempel kan vi säga att du vill generera e-postmeddelanden som ser ut så här:
Hi !Your account is ready, your user name is: You have the following roles assigned:, , ...
För att generera e-postmeddelandekroppar så här kan du använda följande statiska mall:
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}}`
Och tillhandahålla data så här för att exekvera den:
data := mapinterface{}{ "Name": "Bob", "UserName": "bob92", "Roles": string{"dbteam", "uiteam", "tester"},}
Normalt skrivs utdata från mallar till en io.Writer
, så om du vill ha resultatet som en string
, skapa och skriv till en bytes.Buffer
(som implementerar io.Writer
). Exekvera mallen och få resultatet som 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()
Detta kommer att resultera i den förväntade utgången:
Hi Bob!Your account is ready, your user name is: bob92You have the following roles assigned:dbteam, uiteam, tester
Prova det på Go Playground.
Notera också att sedan Go 1.10 finns ett nyare, snabbare, mer specialiserat alternativ till bytes.Buffer
som är: strings.Builder
. Användningen är mycket likartad:
builder := &strings.Builder{}if err := t.Execute(builder, data); err != nil { panic(err)}s := builder.String()
Prova den här på Go Playground.
Notera: du kan också visa resultatet av en mallkörning om du anger os.Stdout
som mål (som också implementerar io.Writer
):
t := template.Must(template.New("email").Parse(emailTmpl))if err := t.Execute(os.Stdout, data); err != nil { panic(err)}
Detta kommer att skriva resultatet direkt till os.Stdout
. Prova detta på Go Playground.