3.4 Dynamic Templates
To wrap up our discussion on Go and web applications, we are going to learn how to take the templates in the last lesson and extend them further to build a blog where we have an unknown number of posts and need our template to adjust accordingly. We will also cover the concept of marshalling data, which is actually just a fancy way of deserializing JSON data from a file and into a custom application type.
1.Introduction3 lessons, 12:09
2.the Basics8 lessons, 1:15:15
2.1Variables and Types11:28
2.2Constants and Comments04:44
3.Building Web Servers in Go4 lessons, 43:38
3.1Building a Basic Web Server10:44
3.2Serving HTML to the Browser12:27
4.Conclusion1 lesson, 01:32
3.4 Dynamic Templates
So we have really come quite far to this point. And now it's time to really push things over the edge to the next level. So far, we have been able to create these templates in HTML off in separate files that we can then inject some data into using a context where we've done things like put in the blog title and the blog author, and stuff like that so far. But what if we wanted to get into a little bit more repetition? Let's say we were truly creating a blog, and we were gonna have several posts, and maybe we had contributing authors and things like that. And so while the data structure that is holding the information about the blog posts is always consistent, the data in and of itself could be different. And that's what we wanna try to get to. We wanna try to get to a point where we can create a flexible template for our site, and then fill it in with all of this data that is dynamically generated somewhere else. So let's take a look at some sample data here. This is a very simple JSON formatted data set, and this is gonna be my sample data. So what I've done here is I've created an array of objects that are going to represent the blog posts, they all have a title, an author, and a body with just some generic test text, some and all that kind of good stuff, just so you can kinda see how we're going to do this. Now, what I've done here is I've created just a simple file, and the idea is that the data that is going to be represented in this application in our website could have come from anywhere. It could have come from a database, it could have come from a web service, it really doesn't make any difference. But to keep things rather simple, since we already know how to read files from disk, I'm just going to put this JSON file on the disk, so that I can read it, just like it was coming from somewhere else. And then I could dynamically create this page and presented to the end user. So what does that do for our template? Well, our template is not gonna change, it's going to be extended a little bit. And let's actually take a look at the code first before we actually start to dig into that template, because we've created a couple new types. And in order for you to understand the template, you're gonna have to understand the types. So I have the existing blog type, which is fine, but now I have a new post type, and so this is where we can start to see how we can create a new type that we can then inject into our page. And as you can see here, we have a couple of the properties that we noticed before title, author, and body. And I'm gonna show you how to go to do this process, but then I also included in here a Publish Date, which then you can continue to play with a little bit and see how you can incorporate that into this template and display something on the screen. But I'm gonna leave that for an exercise for you. And then finally, down at the very bottom here, I kind of, for lack of a better term, created a viewModel type, a BlogViewModel, which is basically a collection of all of the information that's gonna be necessary to display something to the end user using my template. And it was really just a type that I put together to be able to combine both the blog type and the post type, so I could combine them into one object, and then send it up to my template. So now that you've seen these objects, these types, let's go back and take a look at our template. And things haven't changed too much, but as you can see here, we can begin to nest these objects, in these collections and arrays of objects into other objects, and still refer to them via our template. So now, because I have multiple types and multiple properties and different types of objects in my context, I now have to refer to them by their full path. So if I wanna put the title on the screen again, I have to refer to it as .Blog.Title because that's the property from the top viewModel down to blog down to title where I need to get that information. And same goes for the header and same goes for the author, but now I've also introduced another section to the site that's gonna be blog posts, and I did not format this very well. You could definitely put in some CSS and style this up a bit, but I'll also leave that as an exercise for you. So what I've done here is I've created a little bit of a recurring loop here, and we didn't really talk much about range, but in the role of Go, arrange is another way to specify a series of things to iterate over. And the way that it works is the range is going to specify what I wanna iterate over, and in this case, I wanna iterate over the posts array. And for each of the values within that posts array, so it could dynamically grow or shrink over time, I wanna do this markup for all of them. Now, because, this is going to seem a little bit strange to get used to, but when you do something like this, and you start to iterate over a collection within your template, within this scope of this range, the context changes to be the context of what you're iterating over. So outside of this scope, I had to refer to everything as .Blog.Title, and within this scope because I'm within the scope of .Posts, I now only have to refer to whatever is the property of that post that I want to actually put on the screen. So in this case, all I have to say is .Title, .Author, and .Body because this scope is already within the context of the posts collection. So hopefully that makes sense, but as you continue to play with these a little bit more, it will definitely start to make some more sense. All right, so how do we start to put all this stuff together now that we can see how the templates going to work? And the post.json files are going to provide data for us. So all we're really gonna have to do is make a slight modification. We have our new types, we still have loadFile that hasn't changed. Our handler has changed a little bit, main hasn't changed at all, we've introduced a new function. So let's take a look at our handler. Once again, we create our blog object, just like we did before, and now I'm grabbing posts from the loadPosts function. Now, within here, I'm gonna do something very similar to what we did before. I'm going to read the file that contains those posts, but then I'm gonna do something new. I'm going to create a variable that's going to be called posts, but you could call it anything you want. And then it is gonna have the type of the resulting process that I'm about to show you, and the reason I'm making this a slice of post objects is ultimately because that's what I'm looking for in my viewModel, that's what I wanna populate within there, so that I can pass that and execute that on my template. So once I've done that, I am going to take the bytes that came back from reading that JSON file, and I'm going to unmarshal them. Now, unmarshal sounds like a very daunting task, but you've probably heard of this referred to as other places, maybe as deserializing. So really, what we're doing here is we're reading the raw JSON bytes from the file. We're bringing them into our application here in this variable, and then we're gonna convert them from those bytes into an object, or objects represented by the pointer that we're passing in here to a certain object. And that's what we're doing right here when we're creating this posts variable that is actually a slice of post, so that's the reason that we're doing that. So the result of this is that if everything matches up, based on these properties and the structure of these JSON objects, if everything matches up to what our post looks like, then it will succeed. And I will ultimately be given a populated object or interface here. And then I can return those posts, so now posts will contain that collection of post from my JSON file. I will create a new viewModel, which I will populate with the data that I now have. I will go and grab my template, just as I did before, and then I will execute that template using my viewModel. So there's only been a couple of little things that have changed here, but it's become very, very powerful. Now, once again, this loadPosts file is only reading from a file, but it could just as easily have been retrieving data from a database or from a web service or wherever. So now that I've done that, I can come back into my server here, and I'm going to go run, and this is going to be my templates.go. And everything seems to be running. I'll come back into my web browser, refresh my page, and now I'm starting to get some data. So I can see Welcome to my amazing blog by Derek Jensen. And I see that we have two blog posts. We have A Sample Post by Derek Jensen and Another Great Post by John Doe. And as our data increases, coming from our JSON file, then we will see more posts here, and if it decreases, we'll see less. And once again, it could come from anywhere. But the point here is that we can now create these flexible templates using the Go HTML template package, and then start to create some dynamic sites based on the content that we are providing to the sites. So there you have it. You have now created a very nice little application that you can begin to extend and use for an actual blog website if you should so choose. But I would definitely recommend adding a little bit of styling and CSS to it, and make it pop little bit more, but now you have the skills to use Go. Not only to build basic functionality in some executable applications, but also start to build some very cool and flexible dynamic web applications.