Module 1 - Introduction
1. Welcome to the course2. Why Go3. Why start and build a blog?4. What about React/Vue/Angular?5. Getting setup and source filesModule 2 - Tech Stack Walkthrough
1. Introduction to Golang Part 12. Introduction to Golang Part 23. Introduction to Golang Part 34. Structuring Golang Applications5. Templating with Templ6. Just enough interactivity with HTMX7. Getting started with postgres8. Servers, routers and endpointsModule 3 - Creating the MVP
1. What are the minimal requirements?2. Doing some initial plumbing3. Embedding static assets4. Creating our views5. Tailwind & Utility-first CSS6. Embedding Assets7. Styling the Landing Page8. Styling the Article PageModule 4 - Managing Content
1. Choose your own adventure2. Writing in Markdown3. Parsing Markdown to HTML4. Frontmatter and Meta Information5. Serving the Content6. Making our Code examples look niceModule 5 - Adding the Database
1. What is a Migration?2. Our first Migration: Posts Table3. Creating the Database Layer4. Showing the Latest Posts5. Slugs and Human Readable URLsModule 6 - Managing the Blog
1. What are the minimum requirements?2. A new layout approaches3. Creating a rough outline4. Our second migration: Users Table5. Introduction to authentication6. Storing passwords securely7. Authenticating users8. Remember me9. Managing posts using a hypermedia API10. Our third migration: Altering Posts Table11. Only show posts marked readyModule 7 - Adding Subscribers
1. What are the minimum requirements?2. Our fourth migration: Subscribers Table3. Creating the subscription form4. Adding some interactivity with HTMX5. Saving new subscribers in the database6. Verifying subscriber emails7. Our fifth migration: Tokens Table8. Email validation view9. Email validation tokens10. Sending validation emails with SES11. Making it all come togetherTech Stack Walkthrough
Introduction to Golang Part 1
Summary
In this video, I provide a basic introduction to the Go programming language, focusing on its fundamental concepts. I explain that Go is a strongly typed language and introduce key concepts like zero values instead of null, variable declarations (both explicit and short form), and constants. I demonstrate how to work with if statements and switch statements for flow control. I also cover functions, showing how to create them with single and multiple return values, and explain Go's approach to error handling. This video serves as a foundation for the rest of the course.
Transcript
Welcome to module two. This is the first video out of three that will give you a very quick and basic introduction to the Go programming language. This is not exhaustive, there's a lot more to learn, but this will make it so that you at least have some foundations to build upon and all of the rest will be picked up during the rest of the course. But for now, I just want you to be familiar with the basics of the language, how you do variables, loops, functions, all of those kind of things. So everyone can follow along. Go is a strongly typed language. What this means is that we must specify the type of our data. So if a variable, for example, is a string, or if it's an integer, or a boolean. The concept of empty or null does not exist in Go. Instead, Go utilizes what is known as a zero value. So if you don't give a variable, for example, an explicit value, Go would assign that variable the null value of that data type. So if we create a variable here called true or false, and set it to bool, this will now be a false value, since this is the zero value of a boolean. This also happens for strings and integers, and so on and so forth. As mentioned earlier, we must specify what type our data is expected to be. This means that when creating a variable, we must be explicit about the type it has. So for example, let's say we create a variable called apiKey and assign it a type string or we can say apiKey equals super secret string. Both ways are a completely valid way of declaring a variable. The first one is known as an explicit variable declaration while the second one is known as a short variable declaration. Remember when we talked about zero value? Well, the first version of this variable will be initialized with a zero value, right? So it has the value of an empty string. The second version goal would infer the data type of that variable based on its value so it would also be of type string. And both of this, these ways is completely fine. And we will be using both of these in the course going forward wherever each one makes sense. Next, go as constants and we don't need to go into too much detail of the inner workings. If you want to, you can look up a stack versus heap, but for now, just know that a constant is something that's fixed in value at compile time that will, that cannot change. Um, we will go back to what compile time is later, but for now, just know that a constant is something that stays fixed in size that must be known upfront. So you cannot declare something, a constant that can change, um, or something that is foreign, you know, like the compiler needs to know the size of this thing and how much size it needs in memory. So if you take an example, we can go down here and say const API key, constants and super secret. So we just declared a super secret API key that we can reference throughout our program. And the types that you can use for constants are string, boolean, and numerical values. Because all of these has a fixed size in memory that the compiler knows so it can allocate that up front. If statements let you control the flow of your program using certain conditions. In Go, you specified using the if keyword. A boolean condition, and then brackets that will execute the code you want to, you want executed if this condition evaluates to true. And it looks something like this. If API key equals constant super secret, then we execute something in here. And the comment here is just a placeholder for whatever you want to execute, right? We can also say else, which will execute if the first conditional evaluates to false. If you want to have more conditions, we can add what is called an else if. So if you say else if API key equals like not super secret, then we execute that block. And this is how we do if statements in Go. Alternatively, you can use what is known as a switch statement. And a switch statement lets you specify a bunch of cases that if any of these cases match, the inputted variable or value, you do something based on that case, right? Um, and this is often preferred to having a long list of if statements in Go, you tend to have your if statement match the left side so that you can, your reading pattern becomes from top to bottom. If you have a lot of like, if else you will tend to see a lot of logical gates, which can be hard to reason about. So if you have a situation where you do have a lot of different outcomes, different conditions, you need to handle a switch statement can sometimes be a better way to go. And they look something like this. So say switch, and then we say API key again. Now, a switch statement is basically a bunch of cases. So we have a case here saying constant super secret. So if the API key has this value, then this case would trigger. So again, do something. We can add as many cases as we want, and not so secret, can't spell, do something. If we want to have a catch all, if none of our specific cases is matched, then we can provide a default that will trigger if none of the other cases fits. The API key here, right? So do something as well. We don't need to specify the default. We can specify one case or 20 cases, how many ever we want. But this one is optional. You can also, if there are cases where multiple values should be specified to trigger the same operation, you can add those by just using like a comma separating the strings or variables or whatever you provide here. So you can also say a super secret string and in this case, both the constant and this super secret string would match. We will trigger this case. You can provide it with a value or a variable or whatever you want here. So that is how you do switch statements in Go. Functions for the uninitiated is simply a reusable piece of code that performs a specific action. So to create a function in Go, you specify the func keyword, and then you give it a name. So I'm going to do a function called validate API key. And then you can specify some arguments to the function. And I'm going to specify a key of type string. And then we are going to return a bool. So, this function will basically validate an API key. And in here, we will do some sort of validation operation on the key. So just to illustrate, we can have this Boolean variable called isValid. Do some validation here based on a key. And then we will assign the value of that operation to our variable isValid. Because right now, remember, this is a key. A zero value. So it's false right now. We do some validation and then we assign them like true or false. And then we just return is valid. So this is a valid basic function in Go. And how you would then call it is you can go something like this. Is valid. And then you say, and then you pass it our API key. Now down here, you can see that we have this is valid. You can also go down and say, let's just call it two. It doesn't really matter. You can name the return variables up front. So instead of having this thing right here, we could say is valid. And then we already have the name of the return variable. Personally, I'm not a big fan of this, but this is a completely valid way of writing functions in Go. Now Go also has the option of returning multiple values. So let's take the example of our validate API key here. There are potential things that could go wrong in this validation process. If you have done any Go work, you have probably seen the if error equals nil statement, that some people really don't like, I don't mind it because in Go errors are values. So it forces you to treat or handle those values when they occur. So to specify that you have multiple return option, you will also, you will do this just as we saw before with the naming here, right? So we just wrap it is in parentheses and we specify the type of our expected return values. The same thing we can do down here. But if you already have named the return value, you need to name all of them. So here we would say error equals error, right? And this is how you can now return multiple error, multiple values from a function. And we're just going to return nil down here, and we can return, let's just say error plus icon nil. This will make a lot more sense once we get into the course, but just imagine that we have some error. That is "could not validate key." And then we want to check if this error is equal to nil. You're not limited to only two. You can have multiple ones. So we can actually, I don't know, let's just return a string from this one, right? And now we return three values. So let's just, some string doesn't really matter. And the same here, some other string. So you can do this as much as you need, right? Mainly you see probably maximum three, but you could, you can do more if you want to. And then up here, we again, see the assignment mismatch. We can ignore returned values from a function by just doing a underscore. So we don't need to use all of them. We can also just ignore the error if we want to. But yeah, you can do like this or you can name the string saying some string and then you can use it in your program, right? So this is how you do functions and then how you do functions with multiple return values in Go.