LongCut logo

Go Templates - Simple and Powerful

By Donald Feury (dak425)

Summary

## Key takeaways - **Go's built-in template package**: Go includes a powerful and extendable text/template package in its standard library, usable without external frameworks for generating HTML, text, or boilerplate code. [00:10], [00:39] - **HTML vs. Text Templates**: Go offers both `text/template` and `html/template` packages. The HTML version includes extra features for escaping characters to prevent security vulnerabilities like script injection. [00:41], [00:51] - **Understanding the dot '.' in templates**: The 'dot' in Go templates represents the current data context, similar to 'this' in object-oriented languages. Understanding its scope, especially within loops or functions, is key to mastering template syntax. [01:30], [10:26] - **Conditional logic and loops in templates**: Go templates support control structures like `if` for conditionals and `range` for iterating over collections, allowing for dynamic content generation based on data. [06:04], [08:38] - **Extending templates with FuncMaps**: You can inject custom functionality into Go templates using `FuncMaps`, allowing you to call external functions (like `strings.ToUpper`) directly within your templates. [12:51], [14:01] - **Generating code with templates**: Go templates can be used to automatically generate code, such as Go struct definitions, by processing structured data, saving significant manual effort, especially for APIs with many types. [16:37], [21:40]

Topics Covered

  • Go's Template Engine: More Than Just Web Pages?
  • Mastering the Elusive 'Dot' in Go Templates.
  • Unlock Advanced Go Templating with Custom Functions.
  • Clean Up Output: Go Template Whitespace Trimming.
  • Automate Boilerplate Code with Go Templates.

Full Transcript

hey y'all doing doll back there again

and did you know did you know that go

has a template engine baked in this

language yeah a fancy little thing that

saved frameworks like label and PHP has

like the blade template engine and if

you've used Ruby you've probably used

rails and rails has like that embedded

Ruby syntax for templates yeah instead

of using a full-blown framework you can

basically just get that baked into the

language with this little text template

package now here's the thing to note

there are actually two template packages

in go standard library this one which is

one I'm going to be using for all these

examples is text slash template and

there's another one specifically for

HTML now they have almost the exact same

functionality but the HTML one has a few

extra bits of functionality put into it

specifically to properly escape special

characters injuries tml to avoid certain

attack vectors like JavaScript script

tags being injected into your web page

and stuff now if we if we look at this

this is pretty straightforward to use

here's an example that they have on the

documentation and here is the syntax you

use when you're actually like

referencing like a value or action that

you're going to be like injecting a

value into your string and it's like

this double curly braces syntax um you

also see this this dot this this is

probably the most confusing part about

gos template syntax if you can wrap your

head around with this what this freaking

dot means within the various context is

you'll be using templates you've

basically gotten around like 90% of the

the headache around understanding how a

good template so let me just switch over

here and start loops start showing you

some examples so you'll see I have a

string here that just represents a very

simple template it just says hello and

then I am injecting again dot

whatever-the-hell dot is but I will

explain to you what not is

so if we we actually want to put

something in this use this and usually

as a template and then put some data

into it right so what I want to put in

till this is put my name in there so I'm

going to say I'm gonna store this in a

variable name is Donald now I want to

actually get a template back and

interact with so I'm gonna say templates

error equals was a template dot new and

you can name it and the name doesn't

necessarily matter it's more if you're

gonna be using multiple templates I'm

just gonna call it hello and we'll call

parse now parse takes two arguments it

takes whatever the string representation

of your template is so in this case it's

going to be my template string and then

it also can take in what does it I'm

pretty hard uh I said yeah I'm getting

it myself yeah it's just that so back

the run this so and of course you got a

check for errors as usual like this I'm

just gonna say log this is a panic this

is panic it said could not parse now

there's actually have a convenient way

of messing of setting up these new

templates where you don't have to arrow

check every time if that's okay which is

instead of doing it like this you can

actually wrap this template do in this

convenience function that the template

package has called template dot must and

what this will do is if this throws an

error at all it'll panic the runtime

will panic so if if you don't

necessarily need the hair that can't

handle the error because it doesn't work

anyway this actually prevent you from

having to error check it like this

so we have our template and we want to

put our data into it now so we're say

error equals template dot execute so

we're going to execute processing this

template with some kind of data so the

first argument is anything that

implements that satisfies the i/o dot

writer interface and so just for the

make this easy I'm gonna use the I'm

just gonna have a go to standard out so

standard out and then you pass in

whatever the data is that you're going

to put into the template so in that case

it's just named Oh

why are you go I can't I can't type

today if error excuse me

we'll see verse I panic could not

execute template so if I go run main

this what it should do it should just

print out hello Donald right okay okay

say and just to verify that let's say if

I change this to see my last name URI

and I run this again very good lol fury

so there's some there's a couple of

other interesting things you can do with

templates and that is you can I use a

lot of the things that you would

normally use like in why you're doing

normal programming a template such as

conditionals you can use the range

operator to reiterate over collections

of data which is very useful and so

let's do that as an example let's um I'm

gonna have another template string

template string equals let's see let's

let's print hello if my name is Donald

about

actually we're gonna do let's just do it

if if the value I pass in is excuse me

is false

we're just gonna print out nothing or

rip out like go away or something and if

it's true we're going to actually print

out like pillow so let's go do like it's

if dots yeah we're just gonna do that

if dots damn we're going to say I'm just

gonna say hello yeah like that then I

think get the boots and at the end of it

like that and I'm going to parse it like

I did before

templates equals template dot must new

hello to parse templates frame that's

not that's the wrong assignment variable

there I haven't read do error equals

template execute OS STV out and let's

just pass in 0 so 0 will evaluate to

being falsely so this should not print

out anything as we're ado I say that's

just I'm just gonna throw the error away

cuz I don't really need that right now

and this should I should work I think

those go go run man maybe yeah so it

didn't for anything now if I go back

over to it but change this to one so

it's a truth eval you and I run it it

prayed that hello again so let's uh

let's do a range over some values so

let's have some names a name it's gonna

be a slice of strings we have you know

Donald rody just have slices slices

strings like that so we're gonna have

another that was drink and this time

we're to do range over dots and we're

gonna do

hello dots like that and at this one I'm

going to explain what the dot Bank means

because this point you're part like what

the hell is the dot see that should be

oh wait no I gotta go weird and any time

you're doing like the UM the actions

like if and range you have to actually

put an end to basically say that you're

done with the action and we're gonna do

templates equals templates most template

new range our templates range for the

airway rules template dot X execute this

STD out and names so what this should do

actually let me change this one thing

real quick so it's the least read think

but a new line there so that should be

give us a bunch of new lines okay so you

see that I've actually put the new line

up here too but you see hello Donald

Hill Bob hello birdie so let me explain

what the dot thing is you're this point

you're probably understand would tell

the dot is best way for me to explain

what the dot is is if you've come from a

language that has the concept that this

we're self it'll make a lot of sense for

instance when you are in a an instance

of a class object from like say Java or

something

this would refer to like the actual

object that's calling the function right

in the scope of these templates at the

very top level so like maybe right here

the the dot every time you see dot just

think of the word this and when you

think of this it's referring to whatever

was passed into this template let's

execute so in this case this dot is this

named variable which in this case is

just it's just a string if you go to

again this template this dot is just

equal to this number 1 now the rate this

template the dot is equal to this top

level data I passed it in which is just

this slice but what happens when you go

into something that does like an

iteration like this within the context

of this action so this this range each

iteration this dot is equal to whatever

the value is that we are currently

evaluating so the first time that we are

going through this range iteration this

would be equal to not on the second

iteration it would be equal to Bob and

on the last one they'd be equal to

Brewery that's probably the most

straightforward way for me to explain it

if we were interacting with a struct or

something that had properties on it so

like instead of this being strings if

these were Struck's the head properties

you could say like dot and then the name

of the property to get the value off of

that's probably the most straightforward

we've wait for me to explain them now

here's something super neat that you can

do with the templates that I don't think

a lot of people realize you can do this

is you can actually inject additional

functionality that isn't normally

present when you're processing the

templates and you do that with something

that it uses called a func map so if I

go back here and let me see if I can

find it it is down here somewhere

type func map so you'll notice that

there's a function on the template type

here called funks says funks adds the

elements of the argument map to the

templates function map there's there's

like us a base set of functions you can

call and the when you're processing a

template but there's not a lot of them

this is essentially as you do is to

inject additional functions that you can

use to process the text and it says that

it the functions have to be they have to

either return like one value or two and

then the second value always has to be

of type error and what happens is if the

function actually returns an error when

you call like execute execute will

return a so let's um let's add something

to this this template that doesn't have

by default let's give it the Billy to

uppercase all of the strings if so we're

gonna have lets we're gonna use the

exact same template string okay with the

exam but what the exception is the me

paces back down here we're not going to

just do dot we're going to we're gonna

pass in a function that we're gonna call

two upper like that okay and this may

not make a lot of sense right now but it

will very shortly

okay upper so we're gonna say template

equals template dot must template dot

new funks and now I'm going to call was

it funk funk yes and we have to pass

into it a map and let me actually make

that map real quick so I'm gonna call it

a bump map equals a map of strings and

others say there it particularly they

can be whatever so I'm just gonna do

that like this make sure that's it's not

good pointing everything so I'm gonna

say that to upper that's not how you

spell tonight

and I'm gonna say we are there already

is a function in the NGO standard

packages to do this I believe it is

strings dot to upper I believe that's

what it is this I believe that's what it

is yeah so now we're going to say Fox is

equal to this funk map I never recall

parse and we wrap s in our template

string like that and we're gonna throw

this away is equal to template dot

execute OS STD out and we're gonna pass

in our names again so what this should

output is almost the exact same thing as

before but all the names should be

uppercase keep in mind this the upper

casing stuff is not included in the base

set of functions you can normally use in

the template package when you're

processing templates have I run this now

you'll see that the second set they're

all capitalized you've injected

additional functionality that wasn't

there before this is super convenient I

I did this once for a project that I

sort of dead as an experiment in fact

I'm that's the last example I'm going to

show you is a um excuse me an adaptation

of what I did once to essentially

generate code for me so I'm going to go

to it how it does have a totally

different file and like I called it

struck stock ooh yeah so

this is we're gonna pretend that I have

obtained some data somewhere and this

data is of this this structure has name

a description and some fields and a

field has a name a type name and what

we're going to do is we're going to use

this data to generate go struct

definitions for us so you see I've

already defined some data here you just

have to pretend that I got this from

somewhere else in practicality this

example is based off of when I used a

web scraper to scrape a services API

Docs to get the information about there

like the straight in the shape of their

pea types they either expected in

arguments or in responses and use it to

just spit out all these struct

definitions that me how to do it by hand

so you'll see this first one says it has

a name called server and the description

says details about a server it has three

fields an ID as an int that URL to

string and active it's bullying okay we

have another one channel the description

has three fields and then we have a role

it's kind of sort of based on Mike skied

me like discourse way it's laid out more

or less and that we have our template

and you'll see my template you can

actually load in a file instead of just

like parsing an actual just like string

verbatim so let me let's open that up

shall we see split struck templates like

this and here is the template and you're

gonna see a couple of other things I'm

going to explain too so here's our dot

now keep in mind I am passing in a slice

so this top-level dot will be the slice

so I'm ranging over the slice and then

since the things I'm ranging or the

things that are in this slice are strux

the dot here is just whichever

particular struck I'm looking at and I

am referencing a property on the struck

and you'll see that I am assigning the

description property as the

meant really struct and then we have

type and then the name will be the

actual name of the struct struct and

then oh you can you can just have one

set of curly brackets and that it won't

it won't think it's like a template

syntax and then again I'm ranging over

the fields because the fields and the

data struct is itself a slice so I can

range over it and reference each one of

those you'll see there's this little

like - mark at the end here this this

actually has this X's significance if

you have in your open brackets like this

if you have a minus sign with a space in

this case proceeding in this case would

be preceding it this will trim all the

whitespace the to the of the next

section because you'll notice before

when these printed out down here this

was basically kind of verbatim the way

it was but you can use this little minus

sign syntax like trim whitespace either

before after your text that's being

generated and then you have the name

which is the name of the type and then

type name which is just whatever type I

said it was then you know and we're done

with this range then we're done with

this range so

surely this doesn't actually just spit

out code for us that would be crazy

right so if we go down here you'll see

that I am I'm creating a buffer for me

to write the process template into it

because again remember this can take

anything that implements I Oh doc writer

and bytes thought the the buffer type

from the bytes package does do that and

then interestingly enough you know that

little neat utility that go can use to

format your code but you could actually

reference it in the code itself as if

it's in the package call format and it

has a function called source and in

source you pass into it a slice of bytes

representing your source code and it

gives you back a slice of bytes

representing the formatted code and

you'll see down at the end I just I

typecast the slice of bytes into a

string so I could just print out so

let's actually run that and see what it

does shall we we're gonna do go run

Struck's

that's not I suppose trucks trucks don't

go and would you look at that you have

basically pre-generated go code nice

right now this example was pretty like

not really that important but the

example that I was telling you about

that this is based off of it was

actually mixers API rip mixer by the way

because I got interested in it whenever

mixer like joint ninja and I noticed

they had really well documented API

documentation and I managed to write a

web scraper that scraped specifically

the the all of the information about

their types they used under API and holy

thank God did that by the way

because there was about 157 data types

in their API Docs imagine going through

in writing the type definition for 157

strokes no thank you

I basically wrote this in a way that it

took all that information ran it through

a template not dissimilar from this one

right here but this

a little different because there were

some constants and stuff too and boom I

got 157 strokes and in minutes rather

than me saying here for hours doing it

granted I had to clean some of them up

because there were some inconsistencies

in the verbage they were using to

describe certain parts of their data

types but just just imagine how much

time I saved from doing that so keep

that mind if you're going to write a go

package and it's a go package for an API

and they have their types for their API

very well laid out in their Docs

while I write the things up by hand you

could just scrape it with a web scraper

and just spit out all the boilerplate

code so you can get to actually writing

the actual like the actual functions of

stuff so yeah there you go that's all I

have for you today just to make you

aware that go actually has a really nice

template package built into it and it

makes it very it's very powerful and

very convenient to use it also very

extendable because you can pass it in

that func map it allows you to inject

functionality to do it if you liked the

video be sure to drop me a like

subscribe or follow where you have pins

on whatever you're watching is that

chair if you think anybody else would be

able to make use of it if you'd like to

support the channel support these

tutorial videos I should have some links

wherever this is posted again you don't

have to support it all but I would

greatly appreciate it and with that

y'all come on back and I see you next

[Music]

Loading...

Loading video analysis...