So this time around, we want to work with layouts that allow us to simplify our templates, and if
you look at your templates folder right now, we have to about which looks like this, let me hide the
terminal at home, which looks almost exactly the same.
And this information at the top and then this little bit at the bottom.
These are the things we want to have existed in one place and not on every single page of our site.
The rationale for this is pretty straightforward.
If I need to make a change to the top of the site, like here, for example, I'm importing the bootstrap
success if I want it to use some other success, I don't want to have to change it on every single page
of the site.
That's just extremely time consuming.
So what we're going to do is we're going to create a new file in the templates folder and we're going
to call that.
It's just a file.
We're going to call it base layout template.
And it is important that you have this middle part layout.
OK, I would actually use the temporal extension.
You can use HTML or whatever you want to, but HTML is the standard, at least in my world.
So I'm going to create that and it's a new empty file.
Then I'm going to copy everything from the homepage.
I'm going to copy all of it.
I'm going to paste it in here and then I'm going to add a couple of things at the very top.
I'm going to create a new blank line and I'm going to in double curly braces, I'm going to say define
and then in quotes face.
And then at the very bottom of this, right after the closing HTML tag, I'm going to put in double
curly brackets and OK.
And then just to make things format nicely, I will indent everything in between.
All I've done here and this is something you're going to become very familiar with is I've used inside
those double curly braces directives that are specific to go laying templates.
So before these were added, this was just an HTML.
There was nothing special about it all.
It was passed as a goal line template where it looked for these double curly braces and things in between
them to do things didn't find any, so it just served up the HTML5.
And all I've done here is define everything between this tag, define base and this tag.
And I've said everything in between.
That is a as is defined with the name base and it's going to be a layer.
OK, now I'm going to add some other things in here.
Clearly, I don't want this is the home page on every page of the site.
In fact, I'm going to delete everything between those body tags.
I'm just going to delete it and I'm going instead.
I'm going to put a little directive in there.
And that directive is a block.
A content block.
Block is my directive.
And the name is content.
And this seems odd, but I'll explain it to you.
I'm going to put a period after that.
So there's an opening block tag and now I'll put a closing block tag, which is basically nothing more
than the word.
And so I've just defined a section in this layout that says to the goal line and Googling it says to
go line.
What will you see between this opening block and this envelope, this instatement?
This will change on a per template basis.
I might have content I want to stick in there and that content might be just HTML, in which case I
wouldn't need this dot more often.
It's going to include data that I pass from my handlers to the template renderer to render on the template.
And all that DOT means is include whatever data you have with this template and send it to this block
so we can use it if it has to.
Now I define that.
And just to make things simpler, because I'm going to use this later on, I'm going to find two more
blocks up on the top.
I'm going to find a new block, which I'll call success, and I will pass it data as well, and then
I'll have an ending tag for it.
And and then at the bottom, just before the closing body tag, I'm going to have another block called
Jazz for JavaScript.
And again, I need a closing tag.
Now, the reason I'm doing this is that it's entirely possible.
Block j ust dot.
I want to pass it data as well.
It's entirely possible, in fact, likely that I'm going to have some custom access for one page, but
not for another.
And this gives me a place to put it.
That's the only reason it exists.
It's also extremely likely that I'll have some JavaScript which is specific to some pages, but not
others, and this gives me a place to put it.
So all I've done here is to find a template, a layout for our templates that says here's the base template.
Everything might have access entry, it might have a JavaScript entry and it might have a content entry.
And I can say that.
So now I've created this template.
The obvious question is how do I use it?
Well, to start with, let's go back and say simplify our homepage.
Now this.
Hard here from d'Hiv container and to the ending, Dave and all that stuff in between.
That's the only content I want on this template.
I don't want the rest of it.
So I'm going to copy that, too.
So I have it.
And then I'm going to select all of this text and delete it.
And I'm going to start this template with a directive, a go line template directive.
And it's simply the word template.
Use this template, use the template called base and include the data that's passed and then I'll have
an end.
Actually, you don't need an end for that one.
I'm going to delete that just to say don't confuse you.
This is a simple directive that's not closing.
This just says it has no closing tag.
It just says use the template named base.
And this word right here, base corresponds to this word in base layout template.
So now I have to find that.
And when am I going to have it here?
Well, I could have defined and I want to define content.
And it has a closing time, and in between those, I'll post what I copied a little a few minutes ago.
So now look how simple and short this template is.
It says use the base template.
And anywhere on that base template where you find a block name content put this content.
And the fact that I have the dot here means that my data is available for the entire template.
So that's all that I have to do for that.
And I can do exactly the same thing for base layout or so for about Page.
So I come in here, I find the things that I want to be specific to this.
I cut it, delete everything, say use the template base and pass the data to it and then define content.
Paste in my HTML specific to the Web page and close that define tag, and now that is a lot less HTML
to maintain on a per page basis.
So I defined this base layout, I defined the home page and define the about page.
But if I run the application right now, which I'm going to so go run command web Stargirl, there's
only one file so I could put Mango, but I like to get the habit of going Stargirl because I know him
and have more files in there later and run it.
Then switch to my favorite Web browser, open up a browser window and go to local eighty.
Well, I didn't seem to work very well.
What's in there?
If I view the source on this view the while, I'll just go view source.
There's nothing in there.
It's empty.
Why?
Well, because although I've told this template for the homepage, so let's find home again.
I've said use the template base.
Well, I can't find the template base.
And if I look down here, the error messages in the console in my terminal, it says error parsing,
template, template, homepage, template, no such template base.
I need to actually tell go how to render this template that I'm using layouts and that fortunately is
not all that difficult.
So how are we going to do that?
Well, we already know we have a package here called Render.
Right.
And inside of that is where I actually render the template.
So name starts with package name, and that's OK, I don't mind that.
How do I actually make this thing do what I want it to do?
Well, let's think about this for a minute.
So what I need to do is something more sophisticated than simply saying go to the templates directory
right here, find the template with that name and render it.
I actually need to somehow tell it, find all of the based on all of the pages in this folder, whatever
they may be, find the layouts associated with them and combine those into a template that I can actually
serve.
All right.
So what I'm going to do is I'm going to create a new function and I'll call it a render template test
just so I don't overwrite what I have already.
And I'll give it now in my response writer and give it my tampoe string.
So the same arguments.
And I'm going to do things a little bit differently to start with.
I'm going to create something that you may not be familiar with.
It is a go langue map.
It's just a data structure.
Some people call these associative arrays and that would be the closest corresponding thing.
And this is just a data structure that holds whatever I tell it to hold so I can look up things very,
very quickly.
So I'm going to do that by creating something I'm going to call a cache.
When I'm going to create is a template cache that holds all of my templates and it creates it at the
start of the application.
So I create a variable, my cache, and I'm going to assign that the type of map string.
And that I'm going to put in a point or two template, dot template.
And I need to close that with opening and closing curly brackets, which is pretty straightforward.
OK, so that is something that I've just created.
My cache is a map string template template.
All right, so what am I going to do with that?
Well, the first thing I need to do is to tell it you need to go and get all of the files at a particular
location.
OK, so how do I tell you to do that?
Well, first of all, what am I going to get?
I'm going to go get all of the pages, all of the things in this template folder that actually have
the name page in there.
So before the template, I have a I have a page.
Let's go get those so pages.
I'm going to go get those and error.
I'm going to be checking for errors is going to be assigned.
And this is a built in function found in go file path dot Glaube strange name galore, but it actually
kind of makes sense to me to think it through.
And I want to find.
Everything that exists in dot slash templates and then star dot page, dot tempo.
Now all that really does is say go to the templates folder, find everything the templates folder that's
at the root level of my application and get all of the files that start with anything but definitely
end with dot page, dot tempo.
So this is going to select about Dot Page, Dot Temple and home page Tapio and then I'll check for errors.
OK, so if error is not equal to nil then I want to do what.
Well what do I want to do here.
Let's return an error.
So return an error.
Which means up here I have to say it returns the type of error.
OK.
And it's not called er it's called e r r try that again.
Erm all right.
So now I've got my pages, I haven't done anything with them yet so I've got to do something with it.
So now I'm going to use another control structure that you haven't seen yet.
You may have seen it if you've done some work at other programming languages but you haven't seen it
in go.
It's a for loop and the way that for loops working go is really straightforward for and then the first
thing would be index, which I'm going to get rid of in a minute.
But this is for index and then page.
That's just a name that I'm giving.
It is a signed range through pages and then I do something.
So I have two things that are happening here.
For every page that I find, I am going to get the index and the first time through will be zero.
And then then I'm going to get the actual page itself.
Will the page that I get here is a collection or a selection of all the files that is found in this
variable pages.
So it might find about first, therefore I will equal zero.
The first iteration and page will equal about Page Tampoe and then the second time through this will
go to one because we start counting at zero and four loops and the second one and the second value would
be home page temple.
It will not include based on layout because well, it doesn't end in page two.
Now when I do this, what I what am I going to do when I start looping through this?
Well, I've got this information.
The first thing you get is the actual base name of the page, because what it's returning here is actually
not just about page that template, it's turning the full path to that.
And what I want, it's returning the full path to that.
And what I want is the actual name of the page.
And I can get that by saying name is assigned file path, not base page.
All right.
So now I've used this page variable and it's used here.
And from that I've extracted the actual name, which is just about page template.
I don't want the index.
I'm not going to use it.
So I'm actually going to say don't do anything with the index.
Now that I have this name, what do I want to do with it?
Well, I'm going to create a template set and a template set.
It sounds ever so complicated.
It's not all I'm going to do is give it create a new variable test for template set.
And I'm going to check for an error that's assigned the value of template, not new.
And the name I want to use for that template is the actual name I just extracted name and then I want
to give it Funk's.
This template might have some functions and I'm going to give it a word functions which we haven't defined
yet.
But don't worry about that.
And I want to pass files page.
Wow, that's a lot of text, but what is it actually doing?
Well, first of all, let me just do this.
Copy this error check and paste it here.
OK, what's this function.
Well, we haven't seen that what what that actually is yet, but it is something that I am going to
use.
OK, what I'm going to do up here is outside of this function and outside of that function, just out
to the input statement that I'm going to create a new function, OK, a new variable, I'm going to
call it functions.
And all it's going to do, it's equal to template dot.
Func Map will be seeing this shortly.
I'll explain it in a moment, but let's get it typed out first and it's going to be empty, OK, it
has nothing.
So I've created a variable called functions.
It's a type template.
Func map.
What does this do?
Well, I think map is nothing more than a map of functions that I can use in a template.
I am going to, at some point in this course, need to do something in a go line template that is not
built into the language.
Maybe I want to format a date, maybe I want to return the current year, whatever it may be.
It's not built into the templating language, but go allows us to create our own functions and pass
those to the template.
We don't have any yet, but we'll get some later.
Let's just set it up right now because we know we're going to use it.
So now I've created my template set based upon this page.
I've passed an empty variable function.
That will eventually have some functions in there that we can use.
I've checked for errors, so, so far so good.
What happens next?
Well, first of all, we need to find out, does this template match any layouts?
In other words, should I use a layout that's defined for this template with this particular template?
OK, so we're going to check and see if it matches something.
So let's look for the existence of any layouts in this particular folder called templates.
And we can do that by saying matches.
That's a variable that I'm picking.
And I just like it because actually we're checking to see if something matches again.
We'll check for an error.
And that's going to be assigned the value of, once again, this glob thing, file path globe.
And we're going to look in the folder, dot slash, star layout star, dot layout, dot temple.
So that's going to say look for anything, any file in that directory specified here, which is actually
supposed to be dot templates.
Try that again.
Templates start looking the templates directory for any file that ends and layout HTML.
And if you can find one, we're going to do something with it.
But first, let's check for errors to make sure that everything works the way it's supposed to, because
maybe I had a typo in here where I left the letter out and I can't find the necessary directory, but
whatever it's good practice to check for errors, then we're going to look at this variable matches.
If there's at least one thing that it finds in there, then the length of matches will be greater than
zero.
So I can say if Len, which is a built in function go matches, is greater than zero, then I want to
do something.
And what do I want to do?
Well, I want to actually again go to my template set, which I've already created, check for an error
and I want to pass that Glaube so pass Glaube.
And it's going to be, once again, just the path to the templates.
Templates start up template, sort of layout.
Tampoe.
We're going to pass it will check for errors once again, if there's an error, just return the error.
So we've passed it now.
And what do we do with it next?
Well, we're all set off right now for that part.
For that part.
All we need to do at this point is to take that template set that we've just spent all this time creating.
And we need to add it to the cash that we created up here.
We're finally going to use this map we created.
And the way that it works is very simple.
My cash name, which is the actual name of the template, equals the template set I just created.
So I've got that.
I've created it.
And now because I have a function here, return no.
So we've gone to all this trouble of creating render template test, which is going to become rendered
template in just a minute.
And let's go through this again.
What I've done is create a map and a map is just something I can look up very look up a value in very
quickly.
This happens to have a string as its first parameter, the map index.
And I'm using for the index the name of the template in question.
So when I run this, my cache will actually have two entries.
The first one is called about Page Tampoe and the second one is called Home Page Template.
So that's how I can look things up.
And when I look it up, it's going to give me a fully parsed and ready to use template.
So and it's actually a pointer to a template, but same idea for our purposes.
When I need to render a template, I need to have access to this cache and I need to be able to do that
in some way.
That kind of makes sense.
Now, if you look at the way I've built this variable right now, I've actually got this scoped.
So it only exists within this particular function.
And that's not very helpful.
So maybe I should return that as well.
So let me put brackets around this and return to values.
And the first value of their return is exactly what I have right here, a map, string, template,
template.
So let's get that.
And pasted in there.
And we don't need this after, of course, because we're not actually this is how we're referring to
the type.
This is just a type, it's a map with an index of string and the contents are going to be a pointer
to template template.
And we're returning error.
And here we can just return that before the error.
So we'll compile and return that before the error.
So we'll compile return that before the error one more time.
And down here, if everything works the way that it's supposed to, I can now return this cash.
All right.
So we've got this function.
It's all set.
It's going to go through and pass our templates and return something.
Well, let's test it and make sure it actually works.
So what I'm going to do for just the sake of argument to make sure this works is I am going to every
time I render a template, I'm going to create that template set.
So put in here a template cache, I'll call it template cache and all error is assigned render template
test.
And that takes arguments.
It takes a W and it takes uh, we don't even need the template string.
Let's get rid of that.
Let's just leave it right now.
We're not using the writer at the moment, but we will later on and we'll just check for errors.
So I'm going to copy an error check down here.
Just type it out.
It's not going to take that long if error is not equal to nil format, print line error, getting template
cache and the error.
All right.
So that's it.
And if you're not doing anything with that right now, so I better just do this instead.
They're all right.
And now, because we have an error in two places, I don't need to initialize it twice.
So in theory, if I actually run this code, just hit a page on the Web browser, it's going to execute
this.
But I want to make sure it's actually doing it.
So what I'm going to do here is put another format, dot print line page is currently on the page.
So what's going to happen when I every time I hit a page on the website, it's going to call render
template to render it that it's going to execute this code, which I just have here, just to demonstrate
that it's actually building a template cache or finding out if it's not.
And every time that you render a page, this function gets called down here.
It will create our map.
It will go through the find all the necessary pages in template, in the templates folder, and then
it will loop through that range, arrange for those pages and print out the name of the current page,
and that will return a template cache if there are no errors, which we don't use at the moment.
But let's try this out and see if it works.
OK, so let's compile it.
Good, and I'll hit enter a few times just to get blank lines, go back to this page, reload that page
and come back here.
So it said, look at the error passing template.
That's the error we saw last time.
So we can ignore that.
But it actually found the about page and it found the the home page.
So that's exactly what I need.
Perfect.
So let's go back to our code here.
Stop this down or shut this down.
So I'll stop the application and think about what we're going to do next.
What I need to do is somehow to get my cash and use that to render a template.
Hmm.
How am I going to do that?
I think this is long enough for one lecture.
Let's break this one up into two and in the next one will actually make our template, set our cache
of templates, make that usable and show pages using that nice layout we created at the start of this
lecture.
All right.
I'll see you in the next one and we'll actually make this thing work.