Formaterer du en Go-streng uden at udskrive?

jun 28, 2021
admin

Enkle strenge

For “enkle” strenge (typisk det, der passer ind på en linje) er den enkleste løsning at bruge fmt.Sprintf() og venner (fmt.Sprint(), fmt.Sprintln()). Disse er analoge til funktionerne uden startbogstavet S, men disse Sxxx()-varianter returnerer resultatet som et string i stedet for at udskrive det til standardudgangen.

For eksempel:

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

Variablen s initialiseres med værdien:

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

Tip: Hvis du blot ønsker at sammenkæde værdier af forskellige typer, behøver du måske ikke automatisk at bruge Sprintf() (som kræver en formatstreng), da Sprint() gør netop dette. Se dette eksempel:

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

For kun at sammenkæde strings kan du også bruge strings.Join(), hvor du kan angive en brugerdefineret separator string (der skal placeres mellem de strenge, der skal sammenkædes).

Afprøv disse på Go Playground.

Komplekse strenge (dokumenter)

Hvis den streng, du forsøger at oprette, er mere kompleks (f.eks. en e-mailmeddelelse med flere linjer), bliver fmt.Sprintf() mindre læsbar og mindre effektiv (især hvis du skal gøre det mange gange).

Dertil indeholder standardbiblioteket pakkerne text/template og html/template. Disse pakker implementerer datadrevne skabeloner til generering af tekstoutput. html/template er til generering af HTML-output, der er sikkert mod kodeinjektion. Den tilbyder den samme grænseflade som pakke text/template og bør bruges i stedet for text/template, når output er HTML.

Anvendelse af template-pakkerne kræver grundlæggende, at du leverer en statisk skabelon i form af en string-værdi (som kan stamme fra en fil, i hvilket tilfælde du kun leverer filnavnet), som kan indeholde statisk tekst, og handlinger, som behandles og udføres, når motoren behandler skabelonen og genererer output.

Du kan angive parametre, som indgår/substitueres i den statiske skabelon, og som kan styre outputgenereringsprocessen. Typisk form af sådanne parametre er structs og map-værdier, som kan være indlejret i hinanden.

Eksempel:

For eksempel lad os sige, at du ønsker at generere e-mail-meddelelser, der ser således ud:

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

For at generere e-mail-meddelelseskroppe som denne, kan du bruge følgende statiske skabelon:

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

Og levere data som denne til udførelse af den:

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

Normalt skrives output af skabeloner til en io.Writer, så hvis du vil have resultatet som en string, skal du oprette og skrive til en bytes.Buffer (som implementerer io.Writer). Hvis du udfører skabelonen og får 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()

Dette vil resultere i det forventede output:

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

Prøv det på Go Playground.

Og bemærk også, at siden Go 1.10 er der et nyere, hurtigere, mere specialiseret alternativ til bytes.Buffer, som er: strings.Builder. Brugen er meget lig:

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

Prøv denne her på Go Playground.

Bemærk: Du kan også vise resultatet af en skabelonudførelse, hvis du angiver os.Stdout som mål (som også implementerer io.Writer):

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

Dette vil skrive resultatet direkte til os.Stdout. Prøv dette på Go Playground.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.