Go merkkijonon muotoilu ilman tulostusta?
Yksinkertaiset merkkijonot
”Yksinkertaisille” merkkijonoille (tyypillisesti se, mikä mahtuu riville) yksinkertaisin ratkaisu on käyttää fmt.Sprintf()
ja kavereita (fmt.Sprint()
, fmt.Sprintln()
). Nämä ovat analogisia funktioiden kanssa ilman alkukirjainta S
, mutta nämä Sxxx()
-muunnokset palauttavat tuloksen string
sen sijaan, että tulostaisivat ne vakiotulosteeseen.
Esimerkiksi:
s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)
Muuttuja s
alustetaan arvolla:
Hi, my name is Bob and I'm 23 years old.
Vinkki: Jos haluat vain ketjuttaa erityyppisiä arvoja toisiinsa, sinun ei välttämättä tarvitse automaattisesti käyttää Sprintf()
:aa (joka vaatii muotoilumerkkijonon), sillä Sprint()
:llä tehdään juuri tämä. Katso tämä esimerkki:
i := 23s := fmt.Sprint("") // s will be ""
Kun haluat ketjuttaa vain string
-merkkijonoja, voit käyttää myös strings.Join()
, jossa voit määrittää mukautetun erottimen string
(joka sijoitetaan yhdistettävien merkkijonojen väliin).
Kokeile näitä Go Playgroundissa.
Kompleksiset merkkijonot (dokumentit)
Jos merkkijono, jota yrität luoda, on monimutkaisempi (esim. monirivinen sähköpostiviesti), fmt.Sprintf()
:stä tulee vaikeaselkoisempi ja tehottomampi (varsinkin jos joudut tekemään tämän monta kertaa).
Tätä varten standardikirjasto tarjoaa paketit text/template
ja html/template
. Nämä paketit toteuttavat datapohjaisia malleja tekstimuotoisen tulosteen tuottamiseen. html/template
on tarkoitettu koodi-injektiolta turvallisen HTML-tulosteen tuottamiseen. Se tarjoaa saman rajapinnan kuin paketti text/template
, ja sitä tulisi käyttää text/template
:n sijasta aina, kun tuloste on HTML.
Pakettien template
käyttäminen edellyttää periaatteessa, että annat staattisen mallin string
-arvona (joka voi olla peräisin tiedostosta, jolloin annat vain tiedoston nimen), joka voi sisältää staattista tekstiä, ja toimintoja, joita käsitellään ja suoritetaan, kun moottori käsittelee mallia ja tuottaa tulosteen.
Voit antaa parametreja, jotka sisällytetään/korvataan staattiseen malliin ja jotka voivat ohjata tulosteen tuottamisprosessia. Tällaisten parametrien tyypillisiä muotoja ovat struct
s ja map
-arvot, jotka voivat olla sisäkkäisiä.
Esimerkki:
Esitetään esimerkiksi, että haluat tuottaa sähköpostiviestejä, jotka näyttävät tältä:
Hi !Your account is ready, your user name is: You have the following roles assigned:, , ...
Tällaisten sähköpostiviestien runkojen tuottamiseen voit käyttää seuraavaa staattista mallia:
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}}`
Ja antaa tämänkaltaiset tiedot sen suorittamista varten:
data := mapinterface{}{ "Name": "Bob", "UserName": "bob92", "Roles": string{"dbteam", "uiteam", "tester"},}
Normaalisti mallien tulosteet kirjoitetaan io.Writer
:iin, joten jos haluat tuloksen string
:ksi, luo ja kirjoita bytes.Buffer
:iin (joka toteuttaa io.Writer
:n). Suorittamalla mallin ja saamalla tuloksen 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()
Tällöin saat odotetun tulosteen:
Hi Bob!Your account is ready, your user name is: bob92You have the following roles assigned:dbteam, uiteam, tester
Kokeile sitä Go Playgroundissa.
Huomaa myös, että Go 1.10:stä lähtien bytes.Buffer
:lle on saatavilla uudempi, nopeampi ja erikoistuneempi vaihtoehto, joka on: strings.Builder
. Käyttö on hyvin samanlaista:
builder := &strings.Builder{}if err := t.Execute(builder, data); err != nil { panic(err)}s := builder.String()
Kokeile tätä Go Playgroundissa.
Huomaa: voit myös näyttää mallin suorituksen tuloksen, jos annat kohteeksi os.Stdout
(joka myös toteuttaa io.Writer
):
t := template.Must(template.New("email").Parse(emailTmpl))if err := t.Execute(os.Stdout, data); err != nil { panic(err)}
Tämä kirjoittaa tuloksen suoraan os.Stdout
:lle. Kokeile tätä Go Playgroundissa.