Generarea de texte cu template-uri Go

Prezentare generală

Textul este în jurul nostru în calitate de dezvoltatori de software. Codul este text, HTML este text, XNL / JSON / YAML / TOML este text, Markdown este text, CSV este text. Toate aceste formate de text sunt concepute pentru a satisface atât oamenii cât și mașinile. Oamenii ar trebui să poată citi și edita formate textuale cu editori de text simplu. 

Dar există multe cazuri în care trebuie să generați text într-un anumit format. Puteți converti dintr-un format în altul, creați propriul dvs. DSL, generați automat un cod helper sau doar personalizați un e-mail cu informații specifice utilizatorului. Indiferent de necesitate, Go este mai mult decât capabil să vă ajute pe parcurs cu șabloanele sale puternice. 

În acest tutorial, veți învăța despre șabloanele go-outs și cum să le utilizați pentru generarea de text puternic.

Ce sunt șabloanele Go?

Go template-urile sunt obiecte care gestionează un text cu locașuri speciale denumite acțiuni, care sunt închise de două bretele curry: unele acțiuni. Când executați șablonul, îi oferiți o structură Go care are datele deținute de substituenți. 

Iată un exemplu rapid care generează bancuri de bat. O glumă de bat poate avea un format foarte strict. Singurele lucruri care se schimbă sunt identitatea knocker-ului și punchline-ului.

pachetul principal de import ("text / template" "os") tip Joke struct Cine șir string Punchline func principal () t: = template.New (Knock Knock Joke) .Cine cine cine? .Punchline "t.Parse (text) glume: = [] Joke " Etch "," Binecuvântează-te! " _, glumă: = glumele intervalului t.Execute (os.Stdout, glumă) Output: Knock Knock Cine este acolo? Etch Etch cine? Să vă binecuvânteze! Knock Knock Cine este acolo? Vaca merge Cow merge cine? Nu, vaca merge mai departe!

Înțelegerea acțiunilor de șablon

Sintaxa șablonului este foarte puternică și susține acțiuni cum ar fi accesori de date, funcții, conducte, variabile, condiționări și bucle.

Accesorii de date

Accesorii de date sunt foarte simple. Ei doar trag datele din structura de pornire. Aceștia pot realiza și structuri imbricate:

func main () familie: = Familie Parintele: Persoana "Tarzan", Mama: Persoana "Jane", ChildCount: 2, t: = template.New numele este .Father.Name "t.Parse (text) t.Execute (os.Stdout, familie) 

Dacă datele nu sunt structuri, puteți folosi doar . pentru a accesa direct valoarea:

func (): t.Execute (os.Stdout, 1) t.Execute (os.Stdout, "2") t.Execute (os.Stdout, 3.0) t.Execute (os.Stdout, map [string] int "patru": 4 Orice merge: harta [patru: 4] 

Vom vedea mai târziu cum să ne ocupăm de matrice, felii și hărți.

funcţii

Funcțiile ridică într-adevăr ceea ce puteți face cu șabloanele. Există multe funcții globale și puteți adăuga chiar funcții specifice șabloanelor. Lista completă a funcțiilor globale este disponibilă pe site-ul Web Go.

Iată un exemplu de utilizare a printf funcția într-un șablon:

func main () t: = template.New ("") t.Parse ("Păstrați doar 2 zecimale de π: printf"% .2f ". Pi) Ieșire: păstrând doar 2 zecimale π: 3.14 

conducte

Conducte vă permit să aplicați mai multe funcții la valoarea curentă. Combinarea diferitelor funcții extinde în mod semnificativ modurile în care puteți să vă aliniați și să vă aliniați valorile. 

În următorul cod, trimit câte trei funcții. În primul rând, funcția de apel execută funcția de trecere la A executa(). Apoi Len funcția returnează lungimea rezultatului funcției de intrare, care este 3 în acest caz. În cele din urmă, printf funcția imprimă numărul de elemente.

func () t: = template.New ("") t.Parse ('apelare | retur "abc") Ieșire: 3 elemente

variabile

Uneori doriți să reutilizați rezultatul unei conducte complexe de mai multe ori. Cu template-urile Go, puteți defini o variabilă și reutilizați-o de câte ori doriți. Următorul exemplu extrage numele și prenumele din structura de intrare, le citează și le stochează în variabile $ F și $ L. Apoi le face în ordine normală și inversă. 

Un alt trăsnet aici este acela că trec un șablon anonim al șablonului pentru a face codul mai concis și pentru a evita aglomerarea lui cu tipuri care sunt folosite doar într-un singur loc.

func principal () t: = template.New ("") t.Parse ('$ F: = .FirstName | printf "% q"   Normal: $ F $ L Inversare: $ L $ F ') t.Execute (os.Stdout, struct  "," Sayfan ",) Ieșire: Normal:" Gigi "" Sayfan "Revers:" Sayfan "" Gigi "

Condiționalele

Dar să nu ne oprim aici. Puteți să aveți chiar și condiții în șabloanele dvs. Este o în cazul în care-end acțiune și if-else-end acțiune. Clauza if este afișată dacă ieșirea conductei condiționate nu este goală:

func. () t: = template.New ("") t.Parse ('if - - . else Nu există date disponibile end'). Execute (os.Stdout, "42") t.Execute (os.Stdout, "") Ieșire: 42 Nu există date disponibile 

Rețineți că clauza else provoacă o nouă linie, iar textul "Nicio informație disponibilă" nu este în mod semnificativ indentată.

buclele

Go șabloanele au și bucle. Acest lucru este foarte util când datele conțin feliile, hărțile sau alte iterabile. Obiectul de date pentru o buclă poate fi orice obiect iterabil Go ca array, slice, map sau channel. Funcția range vă permite să iterați peste obiectul de date și să creați o ieșire pentru fiecare element. Să vedem cum să repetăm ​​o hartă:

functie principala () t: = template.New ("") e: = 'Nume, Scoruri interval $ k, $ v: , $ s end end 't.Parse (e) t.Execute (os.Stdout, map [string] , 99, "Betty": 54, 96, 78, "Jake": 89, 67, 93 Output: Nume, Scor Betty 54,96,78 Jake 89,67,93 Mike, 88,77,99 

După cum puteți vedea, spațiul alb este încă o problemă. Nu am reușit să găsesc o modalitate decentă de ao aborda în sintaxa șablonului. Va fi nevoie de post-procesare. În teorie, puteți plasa o bordură pentru a decupa spațiul alb care precede sau urmează acțiunile, dar nu funcționează în prezența gamă.

Șabloane de text

Șabloanele de text sunt implementate în pachetul de text / șablon. În plus față de tot ceea ce am văzut până acum, acest pachet poate, de asemenea, să încarce șabloane din fișiere și să compună mai multe șabloane folosind acțiunea șablonului. Obiectul Șablon are multe metode pentru a susține astfel de cazuri avansate de utilizare:

  • ParseFiles ()
  • ParseGlob ()
  • AddParseTree ()
  • Clone ()
  • DefinedTemplates ()
  • Delims ()
  • ExecuteTemplate ()
  • Funcs ()
  • Privește în sus()
  • Opțiune()
  • Șabloane ()

Din cauza limitărilor de spațiu, nu voi mai trece în detaliu (poate într-un alt tutorial).

Șabloane HTML 

Șabloanele HTML sunt definite în pachetul html / template. Are exact aceeași interfață cu pachetul de șabloane de text, dar este proiectat să genereze cod HTML care este sigur de la injectarea codului. Acest lucru se realizează prin dezinfectarea cu atenție a datelor înainte de includerea în șablon. Ipoteza de lucru este că autorii șablonului sunt de încredere, dar datele furnizate șablonului nu pot fi de încredere. 

Asta e important. Dacă aplicați automat șabloanele pe care le primiți din surse neîncrezătoare, atunci pachetul html / template nu vă va proteja. Este responsabilitatea dvs. să verificați șabloanele.

Să vedem diferența dintre ieșirea lui Text / șablon și html / șablon. Când utilizați textul / șablonul, este ușor să introduceți codul JavaScript în ieșirea generată.

pachet import principal ("text / template" "os") func principal () t, _: = template.New (""t.Execute (os.Stdout, d) Ieșire: Bună ziua, ! 

Dar importarea html / șablon in loc de Text / șablon împiedică acest atac, scăpând etichetele de script și paranteze:

Salut, !

Confruntarea cu erorile

Există două tipuri de erori: erori de analiză și erori de execuție. Analiza() funcția analizează textul șablonului și returnează o eroare, pe care am ignorat-o în mostrele de cod, dar în codul de producție doriți să prindeți din timp aceste erori și să le adresați. 

Dacă doriți o ieșire rapidă și murdară, atunci Trebuie sa() metoda ia rezultatul unei metode care se întoarce (* Șablon, eroare)-ca Clone (), Analiza(), sau ParseFiles ()-și panică în cazul în care eroarea nu este zero. Iată cum verificați dacă există o eroare explicită de analiză:

func () e: = "Sunt un șablon rău, ", err: = șablon.New ("") Parse (e) parsarea: '% s'. \ nError:% v \ n "fmt.Printf (msg, e, err) Ieșire: Parola nu a putut fi parsată: 'Sunt un șablon rău, '. Eroare: șablon:: 1: acțiune neașteptată neașteptată în comandă 

Utilizarea Trebuie sa() doar panică dacă ceva nu este în regulă cu șablonul:

func principal () e: = "Sunt un șablon rău, " template.Must (template.New (")) Parse (e)) Output: panic: template:: 1: acțiune în comandă 

Celălalt tip de eroare este o eroare de execuție dacă datele furnizate nu corespund șablonului. Din nou, puteți verifica în mod explicit sau utilizați Trebuie sa() a se panica. Vă recomand să verificați și să aveți un mecanism de recuperare în acest caz. 

De obicei, nu este nevoie să aduceți întregul sistem în jos doar pentru că o intrare nu îndeplinește cerințele. În exemplul următor, șablonul așteaptă un câmp numit Nume pe structura de date, dar ofer un struct cu un câmp numit Numele complet.

functie principala () e: = "Trebuie sa fie un nume: .Name" t, _: = template.New (" struct FullName șir "Gigi Sayfan") dacă err! = nil fmt.Println ("Fail to execute", err) Output: Trebuie să existe un nume: șablon:: 1: 24: execută "" la <.Name>: nu se poate evalua câmpul Name in type struct FullName string 

Concluzie

Go are un sistem de modelare puternic și sofisticat. Este folosit cu mare efect în multe proiecte mari precum Kubernetes și Hugo. Pachetul html / template oferă o unitate sigură de securitate industrială pentru a dezinstala producția sistemelor web. În acest tutorial am abordat toate elementele de bază și unele cazuri de utilizare intermediară. 

Există încă funcții mai avansate în pachetele de șabloane care așteaptă să fie deblocate. Jucați cu șabloane și încorporați-le în programele dvs. Veți fi surprins plăcut cât de concis și lizibil vă arată codul de generare a textului.

Cod