WEBVTT 00:01.290 --> 00:06.120 So last time we got a good start on the Web application and it's time to set up some roots and display 00:06.120 --> 00:10.110 a page, but first, you may have noticed something that I missed somehow last time around. 00:10.530 --> 00:16.680 And that is right here in line forty seven on my code in the main Dargo file, I have this app info 00:16.680 --> 00:23.670 log print line and I neglected to change this to format or print F, which will do the trick. 00:23.700 --> 00:28.200 There are other ways, but this will do it and that will actually do the substitutions because as you 00:28.200 --> 00:34.440 can see down here on the console, it's starting http server in %s mode uncaught percent D. 00:35.290 --> 00:37.800 Now for this time, let's clear the screen. 00:39.510 --> 00:42.470 That's what I wanted, starting in development mode on part four. 00:42.900 --> 00:43.350 All right. 00:43.440 --> 00:45.020 Just a little oversight on my part. 00:45.630 --> 00:49.800 So let's set up some roots and in order to do that, we're going to have to have somewhere for those 00:49.800 --> 00:50.490 roots to go. 00:50.500 --> 00:56.220 So in my Web folder, I'm going to create a new file, which I'll call Handlers Dacko. 00:56.340 --> 01:01.020 And this is where I'll put my handler's subjectivities package declaration package made. 01:01.680 --> 01:07.040 And let's set up a really simple handler and we'll call it virtual terminal. 01:07.080 --> 01:12.870 So I'll create a function with a receiver app pointer to application so it has access to our app config 01:13.380 --> 01:17.420 and I'll call it virtual terminal and it's a handler. 01:17.430 --> 01:19.550 So it takes two arguments, a response writer 01:22.170 --> 01:24.090 and a pointer to a request. 01:26.520 --> 01:36.590 And all I'm going to do right now is just say app dot info log dot print line, hit the handler. 01:36.870 --> 01:38.010 That's all we'll do for right now. 01:38.100 --> 01:39.600 You give me something to point a route to. 01:40.170 --> 01:44.340 So now let's go over to our roots file and let's put it right in here. 01:45.480 --> 01:57.300 And it's just as simple as mux dot get and I'll use the path slash virtual terminal and that points 01:57.300 --> 01:59.070 to a virtual terminal. 02:00.210 --> 02:11.250 OK, now with those little few lines of code, when I run this, go run slash C and slash web, I should 02:11.250 --> 02:19.560 start my application and I should be able to go to a web browser and go to HTP Colon's localhost four 02:19.560 --> 02:24.570 thousand virtual terminal and not see anything, which is what I expected. 02:24.570 --> 02:29.460 But when I look at the output in my terminal, it should say hit the handler and it does. 02:29.460 --> 02:29.940 Perfect. 02:30.750 --> 02:36.990 So let's stop our application and let's actually display a page now inside of my Web folder. 02:37.020 --> 02:38.130 And this is unusual. 02:38.730 --> 02:43.650 It may seem unusual to you if you've taken my other course in building Web applications and go, but 02:43.650 --> 02:45.210 I'm going to put my templates. 02:45.290 --> 02:50.700 I'll use standard go templates in a folder inside my work folder, which I'll call templates. 02:51.390 --> 02:59.310 OK, and I'll explain why when I create another file in my web folder, a new file which I'll call Render 02:59.310 --> 03:02.040 Duko, and this will take care of rendering pages for us. 03:02.070 --> 03:08.490 So let's give it its package declaration package and now let's set some information up. 03:08.490 --> 03:13.440 So the first thing I'll do is I know I'm going to be passing some kinds of information to my template, 03:13.890 --> 03:17.070 so I'm going to create a new type, which I'll call template data. 03:18.450 --> 03:20.940 And it's a struct and it's going to hold a few things. 03:20.940 --> 03:26.240 And I'll put in all the kinds of things I think I might at some point need to pass to a template. 03:26.610 --> 03:33.900 So like, for example, a string map and that will be a map of string string so I can pass a map of 03:33.900 --> 03:45.540 strings to my templates and I'll do the same thing for map map of string and and probably offload map 03:46.200 --> 03:55.320 map of string for thirty two and then just any kind of data which I'll call data and that's a map of 03:55.320 --> 04:00.600 string with the interface type so I can put whatever I need in there. 04:03.930 --> 04:10.110 And I'm probably going to want to pass, say a CSF token and you won't get to this time around but we'll 04:10.110 --> 04:15.570 get to it eventually see a sort of token which will be a string for cross site request, forgery, protection, 04:16.530 --> 04:22.290 flash data, a message that's displayed once and then goes away, maybe warning data. 04:22.440 --> 04:24.420 And I want to display a warning to the user. 04:24.460 --> 04:27.660 It'll just be a string and error, which will also be a string. 04:29.490 --> 04:32.430 And I might also want to say, is the user authenticate? 04:33.550 --> 04:39.170 Again, we're not using most of that right now, indicated what we will at some point before this course 04:39.180 --> 04:39.600 is over. 04:39.600 --> 04:44.910 And I'll just make that an API, which we are going to use. 04:44.940 --> 04:46.430 That's the route to our API. 04:46.440 --> 04:50.970 That'll be a string and CSFs version, which we are going to use. 04:51.300 --> 04:55.900 And we'll make that a capital C like this and a capital S. 04:55.950 --> 04:58.980 S success version, which will also be a string. 05:00.030 --> 05:04.160 And that's that constant defined back in May not go all right. 05:04.200 --> 05:05.570 So there's that form of it. 05:07.560 --> 05:10.710 There's our type now and probably at some point. 05:10.740 --> 05:13.980 And I also want to pass functions to my templates so far functions. 05:14.340 --> 05:18.210 I'll just make it a equal to a template funk map. 05:20.800 --> 05:27.640 And I'll leave it empty for right now and now I'm going to take advantage of goes embed functionality, 05:27.640 --> 05:32.490 something that appeared in the standard library as part of go one point one six. 05:32.500 --> 05:33.970 So we're going to do it like this. 05:34.000 --> 05:40.920 We're going to use a directive as a comment, go embed and we're going to embed the directory templates, 05:41.320 --> 05:41.650 OK? 05:42.490 --> 05:51.210 And now I just say ver and I'll call my variable template FS for template file system embed with us. 05:52.020 --> 05:54.970 OK, and that should have important embed for me and I did. 05:55.530 --> 05:57.310 OK, so this is empty right now. 05:57.310 --> 06:00.000 So we're going to get an error until we put something in this folder. 06:00.370 --> 06:06.100 So what I'll do for the moment is just create a new file in here, which I will call based on layout 06:07.150 --> 06:08.790 dot temple. 06:09.070 --> 06:11.040 It'll be where I put my base layout. 06:11.350 --> 06:13.480 OK, and here I'll just define 06:16.630 --> 06:20.710 my layout to be named face and I'll give it an end. 06:24.580 --> 06:26.530 OK, so go back to rendered. 06:26.530 --> 06:29.640 OK, go and we'll save this ok. 06:29.660 --> 06:30.560 And that error goes away. 06:31.120 --> 06:33.910 So now I have a place to put my templates and that's where we're going to put them. 06:33.940 --> 06:39.010 And the reason I'm doing that is this nice embed functionality that's now part of the standard library 06:39.670 --> 06:45.360 allows me to compile my application, including all of its associated templates into a single binary. 06:45.370 --> 06:47.500 And I think that's really, really convenient. 06:48.190 --> 06:50.380 OK, now let's create another function here. 06:50.460 --> 06:55.780 I'm going to call this one func and it will have the receiver app pointed to application. 06:57.190 --> 07:01.420 And I'm going to call that add default data and then we'll take two arguments. 07:01.420 --> 07:09.460 It will take TD, which is a pointer to template data, and we'll also take the request HDB request. 07:11.230 --> 07:16.170 And for right now, all that's going to do is return TD. 07:16.980 --> 07:18.610 OK, so it's not going to do anything. 07:18.730 --> 07:23.200 It's just going to take what we got as template data and it's going to return it, which of course means 07:23.500 --> 07:25.540 I have to put slash template data there. 07:26.770 --> 07:32.230 This is where we will add any information that's in this struct or a variable that's created with a 07:32.230 --> 07:33.460 type of template. 07:33.460 --> 07:37.960 Data will add that default data using this function, but I'm going to create steps to get things working 07:37.960 --> 07:38.590 for right now. 07:38.980 --> 07:49.770 Now I'll write a function that actually renders a template, OK, so I will say thank you to application. 07:49.780 --> 07:56.590 So we have access to our config render template and it's going to take a few hours and it will seem 07:56.590 --> 08:00.130 like a lot at the beginning, but it'll make sense very, very soon. 08:00.160 --> 08:02.310 OK, so render template. 08:02.320 --> 08:06.530 We'll take our response writer Hibito Response Writer. 08:06.580 --> 08:07.690 So we have somewhere to write. 08:11.430 --> 08:20.100 It will also take a request pointer to an HIV beat up request, and it will take the name of the template 08:20.100 --> 08:25.650 we want to render, which I'm going to call page, which is a string, and it will take a default or 08:25.830 --> 08:28.560 all the default data that will be passed to all templates. 08:29.070 --> 08:31.110 So template data pointer to that. 08:32.040 --> 08:36.150 And it will also take something called Parshall's and that's going to be very Atick. 08:36.670 --> 08:45.180 It will be one zero or more string's past this to try and you OK, and this will potentially return 08:45.180 --> 08:45.540 an error. 08:45.780 --> 08:49.920 OK, that's a long function definition, but that's what we're going to have to work with. 08:50.190 --> 08:53.730 Now, the first thing I'm going to do is create a variable, which I'm going to call T, and that will 08:53.730 --> 08:56.150 be a pointer to template dot template. 08:56.520 --> 09:03.000 OK, and I'll also create a variable called error for E R, which is of type error. 09:03.600 --> 09:04.980 And normally you don't do that. 09:04.980 --> 09:06.480 But you'll see why I'm doing that in a moment. 09:07.650 --> 09:10.830 Now I want to figure out what template do I want to render. 09:10.860 --> 09:17.310 So I'm going to have things like virtual dash terminal page template and that will be a file that exists 09:17.310 --> 09:19.670 in the templates folder inside of the Web folder. 09:20.580 --> 09:23.250 But when I passed the name, I just want to pass terminal. 09:23.670 --> 09:25.890 I don't want terminal page dot temple. 09:25.920 --> 09:26.670 I just want terminal. 09:26.700 --> 09:29.280 So let's build up the names of that template. 09:29.280 --> 09:31.230 Will have some room here. 09:32.460 --> 09:34.290 So I will say template to render. 09:36.600 --> 09:46.470 That's a variable and I'm declaring that will be assigned the value of format s print F and I'm going 09:46.470 --> 09:55.230 to give it up the string like this templates which is the name of the folder percent estcourt page Temple 09:56.250 --> 09:58.020 and I will substitute for the percent. 09:58.020 --> 10:01.000 S page, which I got as parameter to this. 10:01.350 --> 10:05.320 OK, so now I know what template I want to render, ok. 10:05.670 --> 10:13.140 And the first thing I'm going to do here is to check, to see if I have that variable we put in our 10:13.140 --> 10:18.300 application config, that template cache if that exists in the template cache. 10:18.300 --> 10:21.800 And I'll do it the same way you always do when checking to see if something exists in a map. 10:22.110 --> 10:24.050 I'll ignore the first return parameter. 10:24.210 --> 10:30.330 All I care about is the second one, which I'll call template in math, and that will be true if it 10:30.330 --> 10:32.910 exists in the map and false if it does not. 10:32.940 --> 10:39.310 And all I have to do is looking at template cache with the key of the template to render. 10:40.560 --> 10:43.590 So if that exists, this will be true and we can use it. 10:43.620 --> 10:45.940 If it doesn't, it'll be false and we'll have to build it. 10:46.010 --> 10:53.100 OK, but there's another situation where I never want to use the template cache and that's when I'm 10:53.100 --> 10:54.030 in development. 10:54.040 --> 10:59.940 I don't want to be always stopping and starting my application every time I make a change to the file 11:00.090 --> 11:02.160 in of the base layer. 11:02.220 --> 11:04.410 Instead, I want it to happen automatically. 11:04.410 --> 11:06.030 So I'm going to do a simple instict. 11:06.090 --> 11:18.930 I will say, if I've got config on, if that is equal to production and template in map, then I'll 11:18.930 --> 11:19.260 use it. 11:19.440 --> 11:25.040 OK, so t will be equal to the T is the variable we declared right here in line thirty five. 11:25.230 --> 11:33.090 The template I want to work with is going to be equal to after template cache template to render and 11:33.090 --> 11:33.900 then I have my template. 11:34.170 --> 11:41.720 OK, otherwise if we're not in production or it doesn't exist in that map, then we need to build it. 11:41.850 --> 11:45.750 So we have to actually have to pass that template and I can do it right in the side, this statement. 11:45.760 --> 11:46.670 But that's kind of awkward. 11:46.680 --> 11:51.930 I'll put it into its own function, which I'll call pers template, so I'll call it, then I'll write 11:51.930 --> 11:52.410 the function. 11:52.830 --> 11:54.630 T error is assigned. 11:54.630 --> 11:59.460 The value over is equal to after pass template function. 11:59.460 --> 12:02.880 That doesn't exist yet, but we'll write it in a minute and I'll pass it. 12:03.270 --> 12:10.260 Parshall's, which I got as a very odd string at the very last item in the that was passed to this. 12:10.950 --> 12:16.830 I'll pass it Parshall's I'll pass it page, which is the name of the template I want to remember, minus 12:16.830 --> 12:19.950 the extension on the full name template to render. 12:20.640 --> 12:22.740 OK, and I'll check for an error. 12:22.950 --> 12:35.910 If error is not equal to nil then apta error log dot print line error and I'll just return so I don't 12:35.910 --> 12:36.650 want to go any further. 12:36.930 --> 12:42.030 OK, and what I'll return is, I don't know, I have a template data here. 12:42.030 --> 12:46.050 This is an error so that again there I'll return my error. 12:49.290 --> 12:50.010 We'll go any further. 12:50.200 --> 12:54.750 OK, so before we go any further down here, I'll just say return nil. 12:54.760 --> 12:58.140 So this will compile, let's create that first template function. 12:58.620 --> 13:03.090 So func and it has the receiver of pointer to application. 13:04.110 --> 13:09.090 That's called pers template and it takes us parameters partial. 13:09.780 --> 13:17.880 Which is a slice of string page, which is a string and template to render, which is also a string, 13:22.230 --> 13:29.310 and it returns pointer to template template, which is the result of what we're going to get when we 13:29.310 --> 13:30.520 pass and potentially. 13:31.990 --> 13:41.340 OK, first thing we do here is again declare two variables Verrity, which is a pointer to template 13:41.580 --> 13:46.500 template and var error, which is an error like that. 13:48.390 --> 13:52.580 And now we'll build the Parshall's now we haven't got any Parshall's yet, but we will write this code. 13:53.160 --> 13:59.190 Many go templates, as you know, are comprised of the template itself, some parshall's that we want 13:59.190 --> 14:00.450 included in that template. 14:00.780 --> 14:03.790 And the entire template is governed by some base layer. 14:03.840 --> 14:06.420 So we need to deal with the Parshall's if they exist. 14:07.800 --> 14:13.980 So all we have to do here is say if the length of parshall's is greater than zero, then we have some 14:13.980 --> 14:14.900 parshall's to deal with. 14:15.270 --> 14:18.060 So we just range through that slice of strings. 14:18.060 --> 14:23.270 For an X is a sign the value of range through partial. 14:24.240 --> 14:29.400 And what we want to do here is to say Parshall's I. 14:29.760 --> 14:35.910 That index in the string is equal to the format as print f templates. 14:37.570 --> 14:45.640 Again, as print f templates, which is the directory inside the Web directory, which will be embedded 14:45.640 --> 14:49.880 into the final binary slash percent? 14:49.930 --> 14:52.820 S partial template. 14:52.870 --> 14:58.490 That's how we'll need more files and we want to substitute for that text. 14:59.580 --> 15:07.240 OK, and then a little bit further down outside of this if statement, again, I'll say if Lenn of Parshall's. 15:09.860 --> 15:17.120 Is greater than zero, and I'll put it out here and scroll up to give yourself some room, if we do 15:17.120 --> 15:25.340 have parshall's that we have to call our past template function like this t comma error equals template 15:25.970 --> 15:36.350 new and we want to pass it formatted as part of percent Essig, page, temple and page. 15:38.580 --> 15:42.660 And then we want to pass any functions we don't have any, but we're going to eventually, so we'll 15:42.660 --> 15:45.510 put in functions, those will be available to our template. 15:45.900 --> 15:51.060 And after we add the functions, we call Persse first because we're passing a file system. 15:51.090 --> 15:56.720 And if you recall the name of the file system that we specified, the embedded file system was template. 15:58.530 --> 16:03.360 And the next thing we want to pass and it has to come in this order is the layout we're going to use 16:03.360 --> 16:04.070 for any template. 16:04.140 --> 16:13.460 And I'm going to call mine base layout tempo and it's going to be inside the templates folder like that. 16:13.920 --> 16:23.190 So template based layout template then, because we're in the IF statement here that says there are 16:23.190 --> 16:29.650 some partials, we need to include all of the partial file names and that would be as simple as string's 16:29.910 --> 16:32.370 join Parshall's. 16:35.580 --> 16:42.360 Like that, and that will separate the list of partial files with a comma and the last argument we want 16:42.660 --> 16:48.450 is a template to render right there and better spell Parshall's. 16:48.450 --> 16:48.760 Right. 16:50.880 --> 16:53.550 And apparently didn't import the strings package for me. 16:53.580 --> 16:54.620 So let's put that in there. 17:00.250 --> 17:04.990 OK, let's make sure we've got this all right, good, so we're preparing templates to the Parshall's, 17:04.990 --> 17:11.770 a name that doesn't need it pretty PRST or prevented this looks right. 17:11.850 --> 17:13.300 OK, so that's our first one. 17:13.370 --> 17:18.490 And I'm going to copy this whole thing and paste it down here for where the situation occurs that we 17:18.490 --> 17:21.880 don't have templates or parshall's associated with a template. 17:21.910 --> 17:24.540 I only have to do there is take this part of. 17:28.110 --> 17:36.210 OK, so now we have a means of getting our T variable populated with the necessary information, but 17:36.210 --> 17:37.470 of course we have to check for an error. 17:38.280 --> 17:49.740 If error is not equal to nil, then APTA error log print line the error and return nil and the error. 17:50.640 --> 17:53.500 Otherwise, everything worked and we can hand back our template. 17:53.760 --> 17:58.980 But first, since we've gone to the trouble of building it, let's put it in our template cache template 17:58.980 --> 18:05.850 cache and the index will be template to render and that's going to be equal to. 18:06.630 --> 18:12.730 Now it's in our cash and we'll return T and no, because there's no error. 18:14.940 --> 18:16.950 So now we have our parse template function. 18:16.980 --> 18:20.460 So back up here, we're getting our T variable. 18:20.850 --> 18:24.750 We're checking to see if it's in the template cache, if we're in production and the template is in 18:24.750 --> 18:25.110 the map. 18:25.110 --> 18:26.630 If it is, we pull it out of that map. 18:26.640 --> 18:32.430 Otherwise, if we're in development or we're in production and value does not exist in the template 18:32.430 --> 18:35.210 map, then we go and build it by calling Persch template. 18:35.220 --> 18:37.770 So that gives us our T variable at this point. 18:37.830 --> 18:46.020 So now we'll check to see if we have a template that if TD is equal to nil, then we'll set TD equal 18:46.020 --> 18:50.690 to a reference to template data, an empty one like that. 18:51.720 --> 18:53.130 Then we add our default data. 18:53.190 --> 19:02.070 TD equals up, add default data TD plus it takes the second parameter our our request. 19:08.470 --> 19:15.560 Think I made a mistake up here, it returns a pointer to template data that makes more sense. 19:16.110 --> 19:19.260 I think I have those two transposed at one point, but they're all right now. 19:19.270 --> 19:19.980 So let's keep going. 19:20.640 --> 19:26.100 So we get our template data so we check to see if data was passed with the call to add default data. 19:26.490 --> 19:29.670 And if it wasn't, we create an empty template data object. 19:30.420 --> 19:34.590 Then we add our default data and finally we can execute that template. 19:34.860 --> 19:39.020 So error is equal to to execute. 19:39.210 --> 19:40.950 And that requires two parameters. 19:40.950 --> 19:44.790 Our response writer and our template data and we check for error. 19:45.600 --> 19:46.800 Error is not equal to nil. 19:49.080 --> 19:58.440 Then APTA error log print line error and return and we return our error. 20:02.090 --> 20:04.080 Otherwise, things should be good. 20:04.340 --> 20:10.430 So this is a means if we get everything right, of handling the situation where we're we have a very 20:10.430 --> 20:16.340 simple template that has no parshall's and we have a template that has parshall's and we have a template 20:16.340 --> 20:20.650 that is being passed, no data and we have a template that's being passed, some data. 20:21.140 --> 20:23.330 So that should handle all of the situations. 20:23.330 --> 20:27.380 And the great thing about this is when we build those templates, which will take care of in the next 20:27.380 --> 20:34.240 lecture, they're actually embedded into our final binary, which I think is a pretty clean solution. 20:34.400 --> 20:37.970 So let's get started on the templates themselves in the next election.