Golang Tutorial for Beginners | Full Go Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this full course you are going to learn about one of the youngest programming languages that is becoming more and more popular in the cloud engineering world which is go or also commonly known as go link you will learn everything you need to get started with go and start using it in your projects we're going to write a very simple cli application to learn the basics of go so instead of learning the concepts and syntax of go with isolated examples you will learn them while building an actual application throughout the tutorial so first let's see a detailed overview of what you will learn before diving right into the syntax you will first understand why go was even developed its use cases and differences to other programming languages as a next step we will set up our local development environment and see how the basic structure of a go file looks like then as we start writing our simple ticket booking application you will learn the core concepts and syntax like the most common data types such as strings integers booleans as well as arrays slices maps and struts you will also learn about variables and constants about formatted output getting and validating user inputs a concept of pointers in go as well as variable scopes then you will see how to control the application flow with loops if else and switch statements as well as how to encapsulate logic in functions and generally how to organize your code in go packages finally we will make use of go routines to parallelize some of the execution to make our application faster with concurrency so we're gonna learn a lot of things in this course and i hope you are excited to get started also i want to mention that all the demo code from this course is available in a git repository which we will link in the video description so you can follow along easily we have put a lot of effort in creating this course so if by the end of this course you think it was valuable for you let me know by leaving a like and subscribe for more content like this and also be sure to check out techworldwithnana.com for online courses and a complete devops educational program if you want to further educate yourself and bring your career to the next level now for viewers absolutely new to programming in general you can also check out my python course on youtube which is even more targeted to complete beginners in programming and with that let's get started go was created by google in 2007 and open sourced in 2009 so it's a pretty young language now whenever you hear about a new programming language the first question you probably have is why do we need yet another programming language what is the purpose of it or how is it better or different from other already existing languages so before diving into the syntax let's see what was the motivation behind creating the go language well the infrastructure where the applications were deployed changed a lot in the last few years multi-core processors became common and also using cloud infrastructure with hundreds or thousands of servers with multiple processors to deploy applications became pretty universal so infrastructure became much more scalable dynamic and had more capacity however most languages couldn't help in writing applications that would take advantage of these infrastructure improvements so basically you had applications that would just execute one task at a time in order but with infrastructure improvements it was possible to now write applications that would execute tasks in parallel do multiple things at once this way making the application faster and more user-friendly a simple example is if you are using google drive you may be uploading or downloading files and folders but you can keep navigating back and forth in the ui so downloading uploading and navigating the ui all happen in parallel or consider youtube you can be listening to this video then scroll down to the comments write a comment yourself like the video etc so the application allows you to do multiple things at once without affecting any other task and this is a concept of multi-threading so each thread is basically processing one task and you can have many of them running in parallel and this makes applications fast but may also cause some issues for example on google docs many users can work on the same document at the same time so when you have two users changing and adding stuff at the same time to the same document this should work smoothly without one user overriding all the changes that another user is making another example where such issues may happen when things are processed in parallel is a booking system for buying tickets or booking a hotel etc let's say again two users are trying to book the last remaining ticket at the same time of course this should work in a way that no double booking happens and this concept is called concurrency and needs to be handled by developers in code so they must write code that prevents any conflicts between the tasks when multiple tasks are running in parallel and updating the same data and many languages do have features for implementing such applications however the code can get pretty complex and handling and preventing the concurrency issues can be pretty hard and with complexity of course there is always a higher risk of human errors and that's where the main purpose and difference of go comes into the picture so go was designed exactly for that purpose to make writing multi-threaded concurrent applications that take advantage of the new performance infrastructure much easier and we will learn about this in more detail at the end of the course when we use go routines so logically enough the main use case of go or what it's best used for is writing applications that need to be very performant and will run on the modern scaled and distributed infrastructure with hundreds and thousands of servers typically on a cloud platform for developing go they wanted to take the simplicity of syntax of a more high-level language like python and the speed and efficiency of a lower level language like c plus plus so you will see the combination of these things in go and i have to note that go is used on the server side or the back inside of the applications and these types of applications can range from microservices and web applications to database services and so on in fact many cloud technologies or technologies that run on modern cloud environments are actually written in go like docker hashicorp vault kubernetes cockroachdb and so on now on top of this main purpose of go go actually has a lot of other advantages one of them that i already mentioned is it has a very simple syntax which makes your code very maintainable easy to read and extend another advantage is that go applications can be built very fast they are also very fast in startup and also when they're running plus go is very resource efficient which means it uses few resources or it requires fewer resources like cpu and ram to run go is also a compiled language and it compiles actually very quickly into a single binary and you can deploy it and run it on different platforms in a consistent way so no matter which operating system or which environment you're using you can take that same binary and basically use it across different platforms so considering all these benefits of simplicity and speed and so on go is becoming more and more popular for writing simple automation applications and command line interface applications for devops and sre tasks as well so now that we know why go was created and what differentiates it from other languages let's jump right into learning the core concepts and syntax of go now to start writing a go project we're gonna need two software programs first of all we're gonna need go compiler and second we're gonna need an ide or integrated development environment where we're gonna write code for go and also execute it as an id we're gonna use visual studio code which is super easy to download and install so if you don't have it yet on your computer just type in install visual studio code in google and basically on their official page you have the download options for all operating systems so go ahead download and install it so that's the first part i already have visual studio code locally so i'm gonna skip this part and second we're gonna need to install go compiler right now i don't have go locally that's why when i type go it tells me command not found so we're gonna install go which is also super easy again type install go and on their official page you have download and install guide and again for different operating systems i'm working on mac so i'm gonna download the go package for mac awesome once that's downloaded just click on the package and it will show you an installer which basically lets you install go step by step setting up everything necessary in the background so we're gonna do continue install for all users we're going to leave all the defaults install authorize and as you see installation was successful so so if i close this window we can remove the installer and go back to the terminal and type go as you see we have go installed that's why you see a bunch of go commands that you can start using now great so we have everything prepared let's create a folder in which we're gonna write our go project and i'm gonna call it booking app and using visual studio code we're going to write go program in that folder so i'm going to open visual studio code and i'm in the booking app folder you can also simply just open visual studio code and then basically choose a folder that you want to work in and you have the same result and i'm going to make it a little bigger for convenience and there is one more thing that we need to do to prepare our setup and that is installing a go extension inside the visual studio code the extension will basically help us in writing the go code it will give us a nice syntax highlighting intellisense to basically easily navigate our code help with troubleshooting and so on so extensions for different languages make it much easier to write code in that language so let's go ahead and do that to complete our setup and on the left side right here you have the extensions tab so if i click inside and then search go it will give us all the available extensions for visual studio code and the first one with the most downloads is the official one from go team at google and you also have a description of what that extension gives you and that's the extension we're going to use so click on install and that's it now we're all set up to start writing our first go application in visual studio code and for that obviously we need to create a file and this is going to be the main dot go file with dot go extension you will see a bunch of pop-ups here to install things for the go extension so go ahead and click on install all and that will install and set up the rest of the stuff and main dot go is basically a standard name for the main file where the go application code is written and to see that in the file explorer we have this booking app folder and inside we have this main.go file now how do we start writing code in go like printing a simple hello world message to the console let's do print quotes hello world and we already see the first benefit of a go extension because it tells us that this code doesn't work and as you see the error says that go can't find a file called go.mod so the first thing we need to fix is to make our go application into a project and for that we need to basically initialize it that's the error that we get here and to do that we're going to open a terminal in visual studio code new terminal window and this will give us terminal in booking app folder which we're in which is very convenient and here i'm gonna run a go command called go mod or module init and basically name of the project we called it booking app so let's use that name so this is gonna basically initiate our go application into a module or a project and we're calling it booking app so let's execute and save so what this command actually did in the background is it generated this go dot mod file which simply describes the project with the name of the project and the version of go that is used here so the first issue is now fixed now we have another error that says expected package so in go everything is organized into packages and we're going to be using go packages throughout our application and when we create our own application we also have to include it in a package and doing that is actually very simple as the first line of our go application we define keyword package and then name of the package which our application will be part of and the standard name for the main application is package main so now we have an initialized go application which is in a package called main moving on to the next error we now see again a different message that says that a declaration is expected now i have to note here that you may actually have a different sequence of errors so you might see a different message here but i'm going to show it to you with my examples so in this case we have a missing declaration and that is basically goes way of saying i don't know where to start executing this application so give me an entry point and we have to declare the entry point of our application because when we run go applications we need the main starting point for the execution so go needs to know where does it start executing the code on which line because if you have multiple files in the go project you need to give go compiler a starting point the first line of code where the execution starts and the entry point is a main function that go will look for whenever you execute your go application and we create a main function using func keyword name of the function again it has to be called main and we have to put our logic whatever we are executing within that main function so now go will know where to start executing our application and for one go application you're going to have a one main because you can only have one entry point to your application so now we have a slightly changed syntax highlighting for our print function and if we hover over it we see another error message that says undeclared name now we've come to the point where our application belongs to a package we have the entry point so go knows where to start the execution and it sees that print is the first code that it's going to execute but the problem here is that it doesn't know where print is coming from that's why we see undeclared name and print is a function that comes from a go package a built-in package called fmt or format and we have to explicitly import any packages from which we're using the functionality so we're going to do import quotes fmt that's the name of the go package and to use a print function or any function from the package we're going to do fmt dot print and immediately as you see the error is gone and as i mentioned similar to many other programming languages everything is organized into packages so the go program that we installed actually already has some built-in packages with a bunch of functionality that we can use and one of them is this package that we just imported and as i said the packages have functions that we can use so whenever we want to use a built-in go function to print a text to get user input to validate something etc we need to explicitly import it from one of the packages so think of the packages as containers of various functionalities that go gives you readily available for you to use when writing your applications now how do you know which functions are in which packages or let's say if you need to get a user input how do you know in which package you have that functionality available well you actually have to look up the documentation to see that or basically just simply google to find the right package and of course with time when using go and its packages you are going to know the most commonly used packages and all their functionalities and a cool thing we have here is you see this underline under the fmt package and if i hover over it you see a link that actually takes you to the official documentation of the fmt package so here you can actually see what functions you have available in that package and so on so with this we have our first fully functioning go application that we can now execute so let's clean up our terminal and executing a go application is very easy we have go command for it called go run and name of the file that we are executing which is main dot go so go run will basically execute this file it will look for the main function and execute the contents or lines within that function one by one we just have one line so that's getting executed and we're seeing hello world in the output we can do final optimization here to add a new line at the end of this print statement and to do that we're simply going to use a different function from format package called print ln so this will print whatever we pass here with a new line and let's execute that again and there you go now that we have the minimum program structure and know how to run go programs let's start writing our booking application logic the very first thing we need to do in our booking application is to greet our users when they visit the application so let's write some welcome message and information about the conference for which they are booking the tickets so instead of hello world we're gonna write welcome message like welcome to our conference booking application and we can write another message like get your tickets here to attend and again if we execute this we're gonna see our welcome message pretty easy now let's say our conference has a name and we're using this name in many places in our application in the welcome message in the thank you message when the user books the ticket on the ticket itself etc and whenever we have a value like conference name that is used in many places throughout the application it's the most common usage for variables every programming language has a concept of variables where instead of repeating this value everywhere you store it once in a variable assign it a name and now you can reference that value using its variable name wherever you need it in your code now if the value changes you don't have to find and update it in multiple places throughout the application code but you can simply change it in one place where you assigned it to a variable and that's it so how do we create and use variables in go well we have the value like the name of the conference let's call it go conference and we store that value in a variable and we can give that variable whatever name we want like this let's call it a name and finally we tell go that we are creating a variable using a var keyword so this basically lets us store the value go conference the conference name in a variable called name so now we can use that value by referencing the variable name wherever we need it now with variables it's a good practice to create variable names that properly describe what the value is in our case name baby two generic so to make it more specific and clear we can call it a conference name and note the camel case syntax here which is a pretty common variable naming convention in different programming languages including go and if i save those changes you see that we get a red line under our variable definition and that is something specific to go language so in go unlike many other programming languages when we define a variable or when we create a variable with a certain value and we don't use it in the code we get this error that actually says conference name declared but not used so to fix this error we actually have to use that variable and note that same error applies when you import a package but you don't use that package in your code you get the same error that package gets imported but not used which is a very good reminder to clean up your code so to fix this issue we're simply gonna print out that variable value using print line function and again when i save this change the error disappears so let's clean up the terminal output and run our go application again and there you go you see go conference printed out now let's actually use that conference name in our welcome message instead of generic our conference we're going to reference whatever we define as a conference name for that first of all let's delete the print statement and again as a common practice we're going to define the variable at the beginning of the function and we can use the variable within the print message by dividing the actual text that we have here and the variable name with commas inside the print alien function so this will be substituted by conference name and then actual text and the variable name will be separated by commas and let's save this and if i execute our go application again we will see welcome to goconference booking application so it took the value from here also note that the space automatically gets added before and after the variable value now what we also need in our application is the tickets for our conference and let's say we have total of 50 conference tickets available for users to book and for that we will also create a reference called conference tickets to store that value once and then we can reference it as many times as we want so let's call it conference tickets and the value will be 50. we have 50 tickets available now this value actually does not change throughout the application right we have 50 conference tickets and it will always stay 50. while our application is running and for such values that do not change or stay constant instead of variables we have constants now as you might think the conference name could also be constant because it also doesn't change throughout the program but for this example we will leave it as a variable so instead of var keyword here we're going to use const and that will give us the same type of reference as with variables but this time we cannot change the value of this constant but we can use it and reference it in our application exactly the same way as our variables so the const keyword tells go that this value is not allowed to change and if we actually try that and somewhere in the application code change it to some other value and then try to use that like this we get a warning here right away that says cannot assign to conference tickets because it's declared as a constant but if we change it to var and save you see that the warning disappears so let's change it back to const and clean those lines up now when users start booking the tickets obviously we need to keep track of the ticket count so when 50 users book their tickets we inform the rest that the conference is completely sold out so every time someone books a ticket we need to basically reduce the number of available tickets that users can book and for tracking that amount we're going to create another variable for remaining tickets and we're going to call it remaining tickets which again is a variable because as users book their tickets this value will get less and less and it starts at 50 because that's how many tickets we have in total and again we have this warning because we're not using it so let's actually use that in our welcome message to inform the users about how many tickets are available for the conference and how many of them are still remaining so between these two lines i'm going to add another print statement and here we're going to say we have total of this many tickets and this many are still available and if i save this the warning will go away because we are using both of these values in our code so again separating the actual text from the variable reference using commas now let's run our updated application and in the message we have the name of the conference and here it says we have total of 50 tickets and 50 are still available now whenever we're printing our text mixed with variables we can use a function called printf from the format package this function is specifically used for printing formatted data so it tells go how to format the values of the variables and generally it makes writing these kind of outputs easier so with printf this line for example will look like this so instead of print ln we're going to use printf another function from the format package and instead of the conference name reference we're going to use what's called a placeholder and annotate that using percentage sign and v and you see the syntax highlighting here that shows that it's a special character for placeholder but of course we still need to reference whatever variable we want to substitute here right and we do that right here with a comma and then conference name and if i save this and run we have the same output one thing that is different here is the new line is missing because we were using println that automatically added a new line in this case we're gonna add it explicitly using backslash n so that's a character for newline and if i save this and run we have exactly the same output as before now let's do the same for the second print statement first change it to printf take this reference here and substitute it with percentage v do the same for the second variable reference and again we need to replace so basically we need to tell go which variable values should be used to replace those placeholders and of course they should be in a correct order when we have multiple such placeholders so the first one is conference tickets the second one is remaining tickets and again the new line backslash n save it and there you go now as i mentioned printf or print format function allows you to tell go how to format the variables that you are referencing here the percentage v is the default format but you have other specific formats also available if you want the values to be displayed differently and you can see this whole list in the gold documentation under the fmt package link so the percentage v is the one we used we have a lot of other options as well for numbers and text values and so on now sometimes when we create a variable we don't immediately know its value for example when we're getting user input like a user entering their name and date of birth etc in the application we don't know that value before because we don't know what the user is going to enter so we create a variable and later we assign it the value which is possible to do in go just like in other programming languages so let's see the syntax for that so here let's say we define a variable called username and we don't know what the value of that variable is going to be and on the next line we ask the user for their name and this is a syntax for comment so whatever starts with double forward slash signs is basically interpreted as a comment so it's not executed as code so let's say we have some imaginary code here that asks for user input and they and that user name that we get is let's say tom and finally we can actually use that value so we have defined a variable here and then we are assigning a value for that variable later on a separate line however when i save this code you see that we get another warning here that says unexpected newline expecting type so what's the problem here and why is it expecting a type well in go all values have data types and generally in any programming language you have multiple data types for different use cases and go isn't an exception the difference between these languages is however which data types exactly they support so each language has its own set of data types two most basic and common data types are strings and integers for textual data like the welcome message the name of the conference so anything between the quotes basically is a string data type for numeric data like ticket count h and so on we have integer data type and again you see the syntax highlighting for the integers and strings are different because go basically knows this is a string this is an integer so these are the two most basic ones but we're going to learn a few other data types as we go along here however it's important to understand that each data type can be used differently and behaves differently for example you can do calculations with integers but you can't do calculations with strings you can chain or get a subset of a string but you can do that with integers so the main purpose of having types for values in code is to avoid accidentally using an integer as a string or vice versa and use one data type instead of the other which may break your application so when we create variables in go it needs a type now you may be thinking when we created these two variables right here these two variables and a constant we didn't specify a type so why didn't we get the same syntax error here well when we create a variable or constant and assign a value to it immediately on the same line go can imply the data type based on the value so go knows that this is a variable type for string and this is a constant and variable types for integers because of the values but when we do not assign a value immediately go doesn't know what type of value you are going to store here so it asks you to explicitly define a type to make your code basically more robust and prevent you or other developers from accidentally assigning a wrong data type value to that variable later in the code so in this case we need to define a type explicitly how do we define a type super easy at the end we just say this is a variable of string type if i save this the error disappears and again you see the syntax highlighting for the type and the same way we can define a variable for integer type let's say user tickets which is a number of tickets user wants to buy and this is going to be an integer type and somewhere here we're going to ask user for the input and let's say they enter 2 and in the print statement with printf we're going to say user whatever their username booked this many tickets with a new line and reference the respective variables and again let's run this and here we have our output now you probably already noticed something really cool about go especially if you have worked with other programming languages before and that is that while we're writing this code if we make some mistakes if we have errors in our code for example defining a variable and not using it or forgetting to specify a type etc go basically detects those errors before we even run the application so by the time we're ready to execute the application we have fixed a bunch of errors that go identified and highlighted for us in many programming languages that's not the case usually you discover these kind of errors when you run the application not while you're coding and that is a big advantage of go now going back to the types i mentioned that go actually implies the types of these three values automatically and if we wanted we could actually print out the types of variables using the printf function so with fmt printf let's print out the types of these two variables and a constant so conference tickets is whatever type it has then remaining tickets is whatever type this one has and then conference name is percentage t percentage t is a placeholder for the type of the variable that we're referencing here not the value like percentage v but the type so let's pass in those references and save and if we run our application we should see the output here conference tickets is int or integer remaining tickets is in conference name is string so this lets you print type of any variable now if we wanted we could actually define the types explicitly here even though it's not required so we could do conference name as a string and int and int however specifying a type explicitly when go can detect it makes sense when want to specify a different type than what go would detect for example in go specifically again we have multiple times for numeric values so in addition to int or integer type which represents whole numbers we have int 8 in 16 and 32 and int 64 which corresponds to the length of the integer so basically how big or how large the number is and in addition to that we also have uiint or unsigned integer which represents whole numbers like integer but only positive ones so 0 and plus and here's a chart of all the different numeric data types in go and obviously each one has its own purpose so the question is when to use which one and why do we have so many different integer data types for example well this allows you to define data types in a way that the values will automatically be validated so if you're using uiint and assign a negative value to it you will get an error like in our case the number of remaining tickets should never be negative but with int type it can be so somewhere in the code we can actually set it to a negative number like this but if we specify a type uint explicitly instead and save it you see that it will not accept the negative value so setting a type may actually protect our variable from getting a value that it's not supposed to get and obviously you as a developer are not going to assign your variables a wrong value but if you're doing some calculations on your variables or some processing the result of that calculation may be a wrong value we also have float number type which are for numbers with fractional parts so not whole numbers this could be statistical data like a conference attendance compared to last year for example this could also be monetary values like prices of products in an online shop or transactions in an online banking application and so on so basically when a number needs a higher precision float number type needs to be used but as i said there are other data types in go besides textual and numeric types which we will learn as well now there is one more thing in terms of variable definition in go and that is again specific to go is that we have an alternative syntax for creating a variable and assigning it a value directly this is like a syntactic sugar of go language so instead of this syntax for creating a variable we can get rid of the var keyword as well as the type and right here before the equal sign just add a column and this will do the same as before create a variable and assign it a value now note here that with this alternative syntax you cannot declare constants so we cannot do this with constants it only applies to variables and it also doesn't work if you want to explicitly define a type for your variable like here for example now let's clean up our code and let's go back to our ticket booking logic so this is a booking application so want to allow users to book their tickets and for that we want to ask users for their personal information first like first name last name etc and all these values will be then saved into variables like this so we need some logic here that allows the application to ask for user input in order to read user input we use another function from the same format package called skin so basically the format package gives us different functions to print out like this formatted output or read formatted input so it's used for input output processing functionality so let's scan the user input for their first name because instead of assigning the value directly as we did here we want to get that value from the user and then assign it to the username variable now print function like printf or println takes a message as a parameter like this one a formatted message and prints it scan also takes a parameter which is the input it needs to scan and the parameter for scan function is the user input but we don't know what the user will enter as their name so we need a way to save the user input as a variable and then reference that value using that variable name instead of directly assigning it here and let's save it so this is supposed to scan user input and whatever user enters basically assign that value to username variable as a value now if we run this application let's run it you see that it runs it executes all those lines and it just exits it doesn't wait for any user input so we were not able to enter anything and the value of the user here or username variable is also empty so there is one thing that we need to fix here so before the username variable we need to add what's called a pointer like this so what is a pointer simply explained i said that we save a value in a variable in order to use it later so when we create a variable where does that value actually get stored well values are saved in memory on your computer so that 50 or go conference values are actually stored in memory but whenever we reference that value using the variable name we defined go compiler must go and find that value in memory so it needs to know where in memory exactly it is stored or in other words it needs to know the memory address of that value and a pointer is a variable that points to the memory address of another variable that references the actual value 50 for example and pointers in golang are also called special variables so to see that in the code let's actually comment this out and if we print out any variable like remaining tickets for example with value 50 this will give us the actual value 50 but if we print out the pointer this will actually print out the memory location of the remaining tickets variable let's actually see that right here we have value 50 and the next line is a hash which is a memory address for the remaining tickets variable so that's basically a pointer and it's also important to mention that pointers is a concept used in the c programming language but many popular programming languages like java or javascript for example to not have pointers at least not exposed to you as a developer so you will not see the concept of pointers in many other languages so again going back to our scan function instead of passing the value of the username variable which is empty we're passing the memory address of that variable so that scan function will read whatever the user enters and assign that value to that username variable in memory so if i execute the application now you see that it doesn't just exit it actually stops at this line after get your tickets here to attend and it's now waiting for me as a user to input some data and as a username i can input my own name and if i enter it goes to the next line and it prints out whatever is in the username booked to tickets so now we have that value whatever user entered available in our code through this username variable now to make this a little bit user-friendlier we can also ask the user explicitly what we are asking for so we can say enter your first name like this and let's run again and there you go so now we are actually asking the user explicitly what we want and then printing the result out so that's one value now let's read other user data like last name email and number of tickets user wants to book and let's first call this first name and update it everywhere like this let's create last name which is also string and email which is also string and user tickets which we already have which is an int and now one by one let's actually scan all those values i'm going to copy these two lines and we're going to say enter your last name and we're going to save that value that user enters in a last name variable again let's copy and let's say enter your email address and the value will be stored in email variable and finally instead of assigning user tickets directly we're going to ask the user how many tickets they want enter number of tickets and again this will be stored in user tickets variable and at the end let's actually print out some kind of a thank you message to the user with some additional information so let's write thank you first name last name of the user for booking so many tickets you will receive a confirmation email at whatever email address they gave us and don't forget the new line at the end and now let's actually substitute those placeholders with the actual variable references so we have first name last name and here we have the third one user tickets and finally the email address they gave us awesome so let's clean this up and run our program enter your first name nana enter your last name my last name email address something like this and finally number of tickets let's say three tickets and if i enter this is the last skin so now it's gonna execute the print statement that says thank you nashia for booking three tickets you will receive a confirmation email at this email address now we're getting user input but no tickets are being booked the remaining tickets doesn't get reduced it always stays 50. so let's write some simple logic to book the ticket which in our case will be just reducing the number of remaining tickets so after getting user info we will simply add remaining tickets minus user tickets so this will give us some value 50 minus how many tickets user booked and then we have to save it back into the remaining tickets variable to update it right because we have to update the value of this variable by assigning it back now when i save it we see an issue and that is type mismatch of uiint and int because we're doing a calculation on two numbers which have different types one of them is you integer and another one user tickets is an integer so as you see in goal when you do calculations between numbers they have to have the same type one way to handle this issue in many languages is to convert one of them to the other type using various built-in functions that you have available in the language a simple solution for us is to make the user tickets also you in type because users can only book positive number of tickets right they can't book minus one or minus two number of tickets so let's make it you int as well and now the error is gone so that's our super simple booking logic and after the thank you message we're also going to print information about how many tickets are now remaining so let's say this many tickets remaining for this conference remaining tickets and conference name so with these changes let's now run our go application and again enter the user values and let's say we're buying 15 tickets and enter and as you see the remaining tickets are now 35 50 minus 15 that we entered before moving on i want to give a shout out to castin who made this video possible kessen's k10 is the data management platform for kubernetes k10 basically takes off most of the load of doing backup and restore in kubernetes from the cluster administrators it has a very simple ui so it's super easy to work with and has an intelligent logic which does all the heavy lifting for you and with my link you can download k10 for free and get 10 nodes free forever to do your kubernetes backups so make sure to check out the link in the video description and now let's continue now we're saving user data in variables and are booking the ticket for them but when multiple users book the tickets we need to save all these user data in some kind of a list right to keep track of who is attending the event and who booked the tickets and for that we have data types called arrays and slices arrays and slices are commonly used data types in go applications so let's create an array for all the bookings so right here i'm going to create a variable called bookings and this is going to be an array when we define an array the first thing we need is the size because arrays in go have fixed size and for that we use square brackets and within those square brackets we define the length or size of an array and let's say we expect maximum 50 bookings so we're gonna say 50. so the size of an array is basically how many elements can this array hold so as i said array is like a list of bookings or list of elements and with the size 50 we're saying this can have 50 elements in that list the next thing we need to define is the type of the elements this array will contain a data type so what kind of values are we going to store in that is it going to be a list of integers a list of strings etc in our case let's say we want to store a list of names of the users who book the tickets a name is a string so our array is going to be an array of strings so that's the data type and finally we need the actual value right so this is the same syntax as this one right here where we are assigning a value directly to the variable so we need to actually assign a value of an array and we can have an empty array like this or we can already put some elements in the array and let's say these are some of the names inside and this gives us a bookings array with size 50 with three elements already in that array now there are two things i want to mention here first of all because we have to define the type of the elements for the array we can't mix any other type here so we cannot have names and then an integer for example right this will not work and again this is specific to go you can actually mix the types in some other programming languages the second thing i want to mention is that even though we are starting with three elements here we can actually update our array and add new elements up to 50 as well as remove the elements so again this is a variable so we can add new elements to the list and remove that during the application execution and usually when you create an array you actually start with an empty list like this because you don't know the values at this point and as the program executes you basically add new values one by one so that's going to be our starting point and because we are creating an empty array an alternative syntax for this will actually be to define the array variable like this without assigning a value and going with the default empty array but as you learned in this case we have to define the type for the array because go doesn't know the type and again you see here it's expecting type so what is an array type in go well it's actually a combination of the size that we defined which is 50 and the type of the elements it's going to contain like this so this is actually an array type and we're getting this error because we're declaring a variable but not using it so let's actually use it and let's start by adding new elements to that array how can we do that pretty simple actually we have a syntax with indexes so bookings array with index which is the position in which we're adding a new value like this so again our array has 50 empty positions where we can add values and we're saying the position 0 which is the first position let's assign this value and we can say position let's say 10 let's assign a different value but of course normally you would go one by one you would add the next value in the list like this now in our case again we want to add a name of the user that booked the ticket we want to save the first name and the last name of the user so instead of assigning a value directly we're going to say first name and add some space in between and the last name so this will give us first name last name with space separated however as you see here we get an error that first name and last name are not defined because we're using these variables before they are declared here again in a language like javascript for example the order doesn't matter so this would work in javascript but in go you have to use the variable after it has been defined in the code so we're gonna take this assignment and basically move it down here under the logic for updating the remaining tickets and if i save this the error is gone so to wrap this up we're creating an array variable at the beginning which is defined as an array of strings with 50 elements maximum and right here after user has entered their first name last name and booked the ticket we are adding that user's full name to the bookings variable and to also see what's inside the bookings let's actually print out the contents of the array and also some information about the array to see how it actually looks like so let's do fmt print f and first let's print out the whole array placeholder v and newline and this is going to be whole bookings array then let's print the first value which is bookings at index 0 and we need to use capital p here like this then let's also print the type of the array like this and finally let's print the size or length of the array and to get the size of an array we have a built-in function called length with l e n that takes the array as a input so to say and gives us the size of the array and here we need percentage and capital t and now let's actually run our application and see how arrays work book five tickets and here you see all the array information so first of all we have the whole array that has one element which is first name last name of my user and you see that it has square brackets at the beginning and here at the end so basically this represents the space for all the other elements in the array because we have a fixed size of 50 elements and that's why you have a space here then we have just the first value which is this one right here without the brackets the array type is what we actually defined here as a type and then we have array length which is 50. now what happens if we try to add value to this array at an index 52 for example so basically index outside the range of the array size let's try to do that so instead of zero index we're going to do 52. again without running the application go actually detected that your index is out of range or out of bounds and you need to fix that again if you have some calculated number here that you don't know refers to a wrong index go will help you basically detect that error immediately before even running the application now we have one issue with our array because what if you don't know the size of the array when you're creating it let's say we have an array for users who sign up for our newsletter we don't know how many users are going to sign up right this could be anything between zero and indefinite so how can we fixate the size here it could be same in our case because maybe not all 50 tickets get booked or maybe one user basically books all 50 tickets so we have just one booking and an array of size 50 with just one value inside so how can we define a list that is more dynamic in size for such use cases so basically at least where we don't have to specify a size at the beginning but it automatically expands as new elements get added to it well exactly for that use case instead of array we have what's called a slice slice is basically an abstraction of an array so it uses the array type under the hood but has a dynamic size and working with slices is also more efficient than with arrays so generally using slices is actually a better option than using arrays in our application we will also use slice instead of an array and to define a slice we basically create an array without a size definition like this now in an array we added new elements using this index which is not very convenient because for each new user we have to know exactly what is the next index that has a free spot or free place for the next value in slices however we don't need to use the index instead we can just say add the next element to the slice so the syntax for that is append again a built-in function from go just like this length function and this append takes bookings which is our slice and then whatever value we want to add to this slice is a next element whatever index that may be and then we have to assign this back to our slice and as i said this is much nicer because we don't have to keep track of the indices and let's remove this and now we are working with dynamic lists using slice so adding a value to a slice is different than to an array but retrieving a value getting a value from the slice is the same so we can actually leave this syntax like this we can change the wording here from array to slice and now let's run our application again and as you see the slice basically has these brackets directly wrapped around the value it has and the length of a slice is one so as we add new elements it automatically expands and finally just as a reminder note the alternative syntax for creating a slice just like with an array we can also do an empty slice assignment like this or using this alternative syntax we can also create a slice with this syntax so now we're actually saving user information in the bookings list let's actually clean this up before moving on and instead let us print all the bookings in the application like this and we actually need printf and that's our cleaned up application code now even though we are saving the data of the list of users who booked the ticket we only always have just one user because when we run the application we enter information get the ticket and the application exits now of course in real life this would be a web application with a ui and a database connected to it where multiple people can book at the same time from their browsers and the bookings will be persisted in a database but in our case we have a command line interface application so we're using our application only through the terminal so what we're going to do is create a constant loop where the application keeps asking for another ticket booking after one booking is done to simulate booking a ticket multiple times for different users and loops which is a concept that you may already know from other languages is basically used whenever we need to repeat the same logic multiple times now in go specifically loops are actually simplified you don't have different types of loops like while loop and do while loop for each loop and so on you just have one loop which is a for loop and you can use it for all the different use cases so basically you have for loop with different types our first case is super simple use case for a for loop which is that we just want to allow booking over and over again so after the welcome message the logic which basically asks for user input and then books the tickets and then prints out the summary of the booking need to be repeated so right here at the beginning of this logic we're going to write 4 so that's the beginning of a for loop and the syntax of a for loop is curly braces so whatever we put within those curly braces gets repeated in this loop so i'm going to take this whole thing and put it inside the for loop and let's actually fix the indentation like this so we put that logic inside the for loops block and for each line we have basically indentations like this so that's it this will basically keep asking for a new booking after one booking is done and to test that let's run the application this is the first user and now immediately after we got the output of the booking first of all these three lines right here so we have 46 tickets remaining and this is one booking in our bookings list and immediately after that it asks for another user's input and let's fill it out let's do nicole smith and email address and let's say she books three tickets and as you see the remaining tickets got updated from 46 to 43. right so minus three tickets and now we have two bookings in our bookings list the first user and the second user and we can do this basically indefinitely for as many users as we want so to break the application you can do control c and this will basically interrupt and stop the application but of course when we start the application again it will start from scratch right so the bookings variable as well as remaining tickets variable of course gets updated while the application is running right after each rerun everything gets reset now let's do one more thing here at the end of each booking we're printing out the list of users who already bought the tickets and we're printing out their first names and last names but let's say we want to give our users a little bit of privacy and instead of printing their full names we want to only print their first names to display the bookings with a little bit of privacy so basically we want to go through our bookings list our full names bookings slice and for each entry of the full name we want to extract only the first name part and then print only the first name again we're doing the same thing over and over again to different elements of the bookings list so it's a loop but instead of an indefinite loop like the one we're using here that basically never ends we want to loop through a specific list of elements so let's see how we can do that first of all let's define a slice for only the first names let's call it first names and let's use the shortcut syntax for this so this is going to be a slice of first names which are strings and we are starting with an empty list now when i save of course we get an error because we're not using it next what we're going to do is we're going to loop through or iterate through our bookings list grabbing one element at a time and to iterate through a list we have a pretty simple syntax actually we have four again for loop and while we are iterating through this list we get two values for each iteration first we get an index and you learn the index from the arrays it is basically a position of the element in the list this is the first element second element and so on so we get the index for each iteration and we get the element itself and we can call this element whatever we want it's like defining a variable let's call it booking because we have a bookings list so each element inside will be a booking then we have a syntax of colon equals and here we define what list are we actually iterating and getting these two values from which is bookings so we are iterating through bookings and to iterate through a slice we need a range expression range allows us to iterate over elements in different data structures not just arrays or slices but for slices and arrays specifically it gives us back the index and value for each element so this basically defines the whole logic of go through this list and for each iteration give us index and the element value and at the end we have curly braces for defining logic for our for loop so basically we have a for loop inside another for loop so inside these curly braces we have access to each element stored in a booking variable and index of that variable one by one so the booking variable has a full name like nicole smith with a space character between and in order to get the nicole the first name we can simply split the whole string on a space character using goes built-in function called fields like this and the fields function comes from strings package so this will take our full name string split it on empty space and gives us a slice of strings separated by space which in this case is nicole and smith two values so a slice with two elements and we're gonna save that into a variable called names so names will basically be an array containing two elements the first name and the last name and you learned to get the first element of an array or slice we just use index 0 and that's going to be our first name very easy now of course we're using a package and its function so we need to import that package and this is actually one of the cases that i mentioned at the beginning if you want some functionality of go you probably will not know by hard in which package you have such a functionality available and what is the name of the function so of course in this case you just google how to separate strings on space or something similar and you get results probably from ghost official documentation that references this example so let's go ahead and import these strings package right here now here we're just importing one package we haven't actually needed any other but if we want to import multiple packages then we have to enclose it into brackets and each package should be on a new line like this and then close that bracket and there you go now if you scroll down you see a bunch of red lines here which are all about variables that are declared but not used and we're going to fix those one by one first of all we need to save this first name in our first names slice right because we're basically going through these bookings and we're collecting a list of first names in this slice and to add an element to a slice remember we use the append function which has the slice variable inside and the element that we are adding which is actually first name and we have to then assign it back to the slice variable like this so again we're defining a list variable here a slice variable and then within this loop one by one we're adding a first name to this first name slice so at the end of the for loop when we use first names here it's going to have the list of all the first names from the bookings list now we can actually spare us this line here by just grabbing this value here and using it directly in the append so we don't need an additional variable like this so basically when the loop is done collecting the first names we can print it out right here let's do the first names of bookings are and then we have first names instead of the bookings now you see that we still have one error here that we need to fix before we can run our application and that is the index variable that we created here is not being used because we don't actually need this index in our logic but we can't just remove it and just leave booking here it needs to be there because we are expecting two values here so we have to save both of them in a variable so instead we can fix the problem by simply using an underscore in its place which is known as a blank identifier in go underscores are used to identify unused variables so basically we're saying there is a variable here but we just want to ignore it because we don't need to use it and if i save this you see that error is gone and that is because we're telling go that we know that there is a variable defined here that we are explicitly not using that's basically the idea of using underscore so now with these changes let's run our application again and see that only first names get printed out and you see that our application logic works pretty good we have updates in tickets after every booking and at the end of each booking we also get a list of first names printed out and again you can quit the application using control and c great now we have two for loops in our but the first one the indefinite for loop never ends it keeps asking for the next booking but what if all 50 tickets are booked out we need to end the application and say that conference is sold out so after every booking we need to check if the remaining tickets is zero and if it is we end the application otherwise we let it continue and we do that using if else checks which is a concept you have in all programming languages and is super easy so let's see how it works so at the end of the booking within our indefinite for loop right here we make the check to see if the remaining tickets is zero so no tickets are left so we start with if keyword and the expression after the if keyword is called a condition like remaining tickets equals zero and the data type of such conditional statement is a boolean true or false so either this statement is true remaining tickets is really zero or it's false so we're telling the program if this condition is true then execute the code within these curly braces or within the if statement block if this condition is not true then skip the execution of whatever code is defined here and skip to the next line which in our case is the next iteration of our for loop so if the remaining tickets is zero we want to basically end the program so here is going to be logic for quitting the application so first let's actually print out a message for the user saying something like our conference is booked out come back next year and after that we end the application how do we do that we basically break the loop using break keyword so this will basically end the loop which means the application execution is over because there is nothing after the for loop right application ends so as i said this expression here or the value of this expression is of a boolean data type so we should have a boolean type keyword for that and be able to create variables of that type as well right just like for other data types so i could actually take this whole expression and save it into a variable which we can call no tickets remaining which is of a boolean type and then we can use this variable as a conditional of the if statement again with an alternative syntax we can write this expression like this and by the way note the syntax for double equal signs here instead of one equal sign so one equal sign is for assigning values to variables double equal sign is for comparing two values to each other again nothing specific to go this is actually same in other programming languages now since we're using this variable only once here there's actually no need to save this expression into a separate variable so i'm going to change it back to before and leave it directly in the if statement so let's actually test that our logic works and the application ends when users have booked all 50 tickets so let's run the application provide the data and let's actually take all 50 tickets at once like this and as you see after it printed the first names of bookings right here we went to the next line so that remaining tickets equals 0 is true so it so this condition was true and because of that it actually executed these two lines and it printed out our conference is booked out come back next year and it broke out of the loop which ended the program now this makes sure that the program ends when all tickets are booked but what if a user wants to book more tickets than available so what if i typed 52 instead of 50. let's see what would happen in this case with our application so let's run it again and i'm going to book 52 tickets and this is the output first of all we have this weird number of tickets remaining and second the application didn't end it actually continues to ask for another user input so as you see our application cannot handle when user wants to book more than available number of tickets and the reason why application didn't end even though we exceeded the ticket amount is because the remaining tickets is not zero anymore it's this number here that's why these two lines were not executed so let's fix this issue and to do that before the booking happens right here where we take the remaining tickets and we deduct the user tickets from it before that even happens we need to check so we need another if statement to check whether user tickets is greater than the remaining tickets so if user is trying to book more tickets than is available again very easy we have if and then condition which says user tickets is more than remaining tickets right so this is going to be an invalid input from the user so we need to tell the user something like we only have this many tickets remaining so you can't book so many tickets and let's substitute those values so we have remaining tickets and this is the user tickets that they're trying to book so we inform the user about their wrong input but we also have to end the program because if this is true then all this rest of the code should not be executed right the ticket should not be booked so same is right here we break from the loop which ends the program so this break here will basically tell go to skip execution of the rest of the code in the iteration and stop the loop so all of these will be skipped so let's test our logic and try with 52 again and as you see the program says we only have 50 tickets remaining so you can't book 52 tickets and as you see none of the next lines gets executed and the program exits so now we are handling an invalid input from the user to protect our application from the outcome that we saw previously now let's say we don't want to end the application if user wants to book more tickets than remaining we want to allow them to try to book again with the corrected number of tickets so we don't want to stop the for loop completely with break we want to tell the user hey you're trying to book an incorrect number of tickets so please try again so we want to skip all of these to the next iteration of the for loop instead of breaking out of the for loop completely and we can do that also very easily using another instruction called continue so instead of break we say continue to the next iteration so continue just like break we'll skip all of this but instead of ending the loop it will basically go to the next iteration of the loop so let's try that as well let's do 52 again and you see the message gets printed out you can't book so many tickets but it skips to the next iteration and it starts with enter your first name again so user has another chance to enter correct amount so this makes our application a little bit more user-friendly now what if we wanted to check for the reverse condition and check if user wants to book less tickets than available or exactly the same number how could we do that first we change the expression to less than or equal so user tickets is either exactly same as remaining tickets or is less and we say if this condition is true so it's a valid input from the user then everything is great they can book the ticket so this whole logic here can be executed so instead of these two lines i'm going to put this outside of the if block so instead this logic will be executed so we are reversing the check and don't forget to fix the indentation here so if this condition is true then this logic should be executed which actually books the tickets now what about this code here where does this logic go well after the if block is finished we add an else statement which says otherwise so if this is not true it's false in that case execute code in this block and that's where this logic will go so basically either at any iteration either the if block will get executed or else block right so this is an if else statement and this basically logic wise does exactly the same as before we just changed the condition here and because only one of those blocks will be executed we don't need the continue part here to skip the booking logic right because the booking logic is in its own block so say so let's move the continue and save and if i test this again and try 52 you will see the error message so this line was executed the else block basically and without the continue keyword it skipped to the next iteration because that's actually the next line of the code after the else block now let's say we wanted to do something different if the user tickets and remaining tickets were exactly equal so if that was the case we wanted to do something completely different than what we're doing here or here so where could we put this logic in that case we would split up this condition so here we would say if user tickets is less than remaining tickets then do whatever is defined here otherwise else if user tickets is exactly equal to remaining tickets then do something else and finally if none of these are true so this is false and this is also false then execute the else block and you can have as many else if statements in between if and else as you want but you can only have one if statement and one final else statement now let's revert this because we're not doing anything different here and let's revert back to our if else statement now there is another place where we use conditionals that are true or false and that's in for loops so in addition to looping through a list like this we can also say execute the code in a loop for as long as a specific condition is true like execute code in this block within this for loop for as long as remaining tickets is more than zero or as long as the size of the bookings list is less than 50 or even a combination of both like this so we can use the same conditions that we saw in ifall statements as the for loop conditions and tell our program to execute whatever code is inside that for loop as long as this condition is true as soon as it becomes false the for loop execution is over now you may be thinking at this point why didn't we have any condition in our infinite for loop why doesn't it say anything well since the conditions can be true or false an infinite loop can be written by using condition true so basically hard coding aesthetic true will make this loop an infinite loop and that's what we have and whenever we have that we can just leave out the condition and have for loop with no condition and that's going to be the same as saying for true and that's why we don't have to explicitly specify condition but again as i said if you want to write a for loop that only runs as long as a specific condition is true you can define that condition right here another common use case for if else statements is user input validation in our application we are allowing users to enter their data but users don't always enter data correctly either intentionally or unintentionally and we developers must make sure that our application doesn't crash when user puts in bad input so we have to make sure that our application is so robust that it can actually handle any type of bad user input and the way to do that is to always check whether the user input contains valid information any unexpected values and so on so in our case let's check a couple of things in user input that we're expecting so these are the four pieces of data that we are getting from the user and we want to check all of those first let's check that the names that user provides are valid the first name and last name and let's say the valid name for us is a string with at least two characters now if the user provided a wrong name this would not crash the application but we want to make sure that users are not spamming our application and are actually giving correct information at least we try to partially check that and again we have to do the validation part before the booking logic gets executed right because if they entered invalid data we don't allow the booking so right here let's check that first name and last name length is at least two characters but we're not going to do anything with it yet we will just save it into a variable and use it later now to check the length of a string we have the built-in function called len length which you already learned from arrays and slices so for arrays and slices this checks the size of the list for strings it checks the size of the characters so how many characters are in a string so first name length should be at least two so it can be two as well that's why we're going to do greater than or equal to two and the same should be true for the last name so in addition to that we also want to validate last name in the same statement and we can do that or we can chain these two conditions using end characters again note the double ampersand signs so this basically says this condition and this condition so this is going to be check for last name and whatever value of this expression again assign it to a boolean variable and we're going to call it is valid name again we can skip the boolean type because go can imply from the value that it's a boolean type so we can save that and we can also use the alternative syntax like this so again if user entered the first name that is at least two characters long and last name which is also at least two characters long then this whole thing will be true and we're gonna assign the true to is valid name variable now if any one of those is false so if first name is valid but last name is not or vice versa then this whole expression will be also false and that false value will then be assigned to is valid name variable now let's validate the email address and let's say for email address we want to make sure they're not entering an invalid email format so we're going to check that the value of email or the string contains the it sign now you already learned the strings package from which we use this fields function and the same strings package actually has a function called contains that takes a string as a first input and then a character or multiple characters that we want to search in that string and this will actually give us a boolean result back so if the string contains this character or these characters then it will give us true back if not then it's going to be false so we can call this is valid email and assign this whole value to it so we assume if email user gave us contains this character then it is a valid email if not then it's not valid and finally let's check the user tickets and validate that user didn't enter a number of tickets which is negative or zero so it has to be positive number greater than zero so again user tickets is more than zero will be a valid ticket count now we have another check for the user tickets which is that it's a less than remaining ticket so a user cannot book more tickets than available so that's going to be another validation for this input and we can actually add that right here also with this end sign so both of these expressions need to be true so that we have a valid user ticket if any one of those is wrong let's say user tickets is a positive number but it's more than remaining tickets then it's going to be invalid input so let's call this is valid ticket number and here we have our user input validations so as i said we can chain multiple conditions like this with double end sign to make sure both of these are true to give us a valid ticket number we can also chain conditions with or instead of end let's say the conference is taking place in two cities singapore and london and user can choose which one they want to go to or which location they want to attend so they can choose between those two cities but they can't enter some random city that is not valid so in that case we could have a check is valid city where let's say if we had the city as an input we would check if it's either singapore or london so city cannot have both of these values right it has to have either singapore or london if it has some other value then it is an invalid city but if it's valid then it should be either or so in this case we chain this condition using or instead of int well sometimes we need to check whether the user did not enter a specific value for example let's say we want to check is invalid city which means user didn't enter either singapore so the city is not singapore and it's also not london so basically if both of these conditions are true so the city the value of the city is not singapore and is not london then is invalid city is true so this here is a negation or not equal and it may be a little bit confusing than positive statements like equal or greater than etc so if this is more confusing than the previous statement then what you could also do is revert this back to is valid city and then using that exclamation mark you can negate the result of this so basically this statement with exclamation mark is valid city is exactly the same as the negative check that i just showed you and you could use this in the if statement of course like this okay now let's clean up all these examples and go back to our user input checks we have saved all these checks in variables so now it's time to use those variables in the if statement and execute the booking only if all the user input values are valid and skip the booking if at least one of those user inputs are invalid so if name and email are correct but the ticket number is invalid of course we want to skip the booking so in the if statement we check if is valid name is true and is valid email is also true and is valid ticket number is also true so all three have to be true in order to execute the booking so again we're chaining this with end symbols which means all of these three have to be true in order to execute the booking and if i save this we also get rid of the error and if any of the user inputs is wrong we're going to inform the users about that saying using a simple message that says your input data is invalid try again let's save it and let's actually test that our validation logic works so i'm going to put in first name which is just one character and all the other stuff are correct as you see we get invalid data input let's now try a wrong email address without the add sign and again invalid input data and you can also test ticket number and so on so now we have some kind of protection in our application against bad user input as i said the bad or invalid user input can be intentional or unintentional sometimes users accidentally enter wrong information so we could optimize our application to tell the user what they actually entered incorrectly so they can correct it so instead of this generic message here which says your input data is invalid we're going to say exactly what they entered wrong so right here we're going to have if statements that check which of the inputs were actually wrong so we're going to say if is valid name is not true remember the negation with exclamation mark so if name is invalid so this translates to is invalid name in that case we're going to print first name or last name you entered is too short we're going to do the same for email and we're going to say if email is invalid or if is valid email is not true we're going to print a message that says email address you entered does not contain at sign and finally is not valid ticket number we're going to say number of tickets you entered is invalid and we don't need this generic message here and note that we don't have else here we just have if statements because we want each of these statements to be executed because they might have entered all these data wrong wrong name wrong email wrong ticket number so in that case we want to say your name is wrong your email is wrong the number of tickets is invalid if this were else if conditions like this and user had entered invalid name then this would be true and this line would be executed and the else blocks will be skipped because as i said with if else or if else if statements only one of the blocks gets executed not all of them or not multiple of them that's why we're gonna revert it back to if statements and now let's actually try to input a bunch of wrong data like this wrong email number of tickets zero and we get all of these messages it says the name is too short email is invalid and number of tickets is also invalid so now user knows exactly what they entered wrong so as you see if else statements are super important in applications because they basically control the whole application flow it's like a decision tree right we do different things based on different conditions now let's see another concept in programming which is similar to e-file statements which is switch statement let's say our conference is held in six different cities and for most of the cities we have different booking processes and the data we are asking from users so the application logic is basically different based on for which city you want to book the conference ticket so at the beginning of the application we need to check which city user selected and based on that selection we then execute a different code block now if we have to check for six different cities having six if else statements may not be optimal and for such cases we have switch statements now we're not going to execute this code so i'm just going to show you the example syntax right here of how switch statements actually look like so let's say we have this city variable that user basically selects and let's say the user selected london and right here we need to check which of the six cities user wants to book tickets for so first we have the switch keyword that checks the value of city and here we have multiple cases so case one is city value equals new york in which case we want to execute code for booking new york conference tickets another case or another possible value for city is singapore and again here we would execute code for booking a singapore conference tickets in other case let's say we have london again some code here and i'm just going to copy and let's do mexico city and finally hong kong and after each case we have we need the colon so all these are possible values for city so these are where the conferences are held but as i said users sometimes enter invalid data so we also need to handle when the city has none of these values and that's going to be a default case in the switch statement so basically when none of these are true then we execute a code block which let's say prints out no valid city selected so that's like the else in the e-file statement so switch just like e-files basically controls the application flow and based on a value of whatever variable we pass into switch we execute a different logic in our application now let's say the booking logic for london and berlin is the same as well as booking logic for singapore and hong kong is also the same so in this case we don't want to duplicate the code instead we want to consolidate those two cases saying if the city is london or berlin then execute this code and we can also do that in switch statement by listing all the possible values like this and this will be the same logic for london and berlin and as i said for these two cities as well like this so basically in switch statements you can also consolidate multiple values and execute a certain logic for multiple values so that's how switch statements work again let's clean this up and get back to our booking logic now our super simple application became already pretty crowded we have all this code in our main function that keeps on growing so it would be nice to start cleaning it up by taking parts of the code that do one specific thing and putting them in functions with some descriptive name so we encapsulate a code block into its own container called a function give it a name that makes it immediately clear what that code block does and use that block of code simply by calling the function by its name so let's see how to write functions in go well in fact we have already created a function at the beginning which was the main function so the same way after the main function ends right here that's the end of the main function block we create another one using a func keyword then again name of the function and let's call this one greet users and after that we have again function block using the curly braces so each function has its own block and when we call the function then whatever code is inside those curly braces gets executed like a print statement which says welcome to our conference so we have created a simple function that basically just prints out welcome to our conference now when we run our application this code will not get executed because when we create or define a function it basically just stores whatever code is inside for later use but it doesn't actually execute it for that we need to explicitly execute or call the function inside the main function because this is as i mentioned at the very beginning this is the function that go will look for to start the execution so if we create other functions we have to explicitly call them inside the main function so that code inside them gets executed and calling a function is super easy let's say right here at the beginning we want to call grid users function that will then print out the welcome message so if we run our application we have this welcome to our conference which comes from greet users function and then of course we have whatever we define in the main now let's say we want to greet users with the conference name instead of just a generic welcome to our conference so basically the same way as we're doing right here so how can we give the grid users function the value of the conference name variable which we defined here well we can pass it as an input parameter so we can hand it over to greet user's function saying here is the value of conference name variable you can use it inside your function block in your code by just passing it within the brackets but we also need to tell the function itself that it is expecting a parameter we can just throw some parameters to a function randomly we have to expect it explicitly here as well so in the function definition within the brackets we're going to define that parameter using either the same name as the variable that we're using or we can also give it a completely different name it's up to us so we can call it whatever we want and we also have to specify its type because remember variables in go have to have types so we're telling this function you're expecting an input parameter called conf name which is of type string so think of this as a variable inside a function this is very similar to doing this inside a function and that's actually what happens in the background when the function gets called and then you can use this variable or this variable inside this function block and that's what we're going to do we're going to say welcome to booking application and use the conf name value so now if we run the application and we forgot the new line here we got exactly same output as on this line so we basically extracted this code into a function so we don't need this one and let's actually put the whole greeting logic into our grid function so i'm going to take this and in the grid users function let's edit right here and the same way that we pass the conference name we also need to pass these two values because we have to have them available within the function so we have to pass them as input parameters and as i said we can call these whatever we want like conf tickets which is integer and let's call the other one remaining tickets which is u integer unsigned integer like this and of course now whenever we call this function we have to pass all three parameters otherwise we're gonna get an error like here it says not enough arguments so let's pass those two values as well first one is conference tickets this value and then we have the remaining tickets save and the error is gone so we replaced these print lines with a function call like this which makes our main function a little bit cleaner and now if we run the application we should actually get exactly the same output as before we had the function and as you see we have our welcome statement all the values are substituted everything looks fine so we extracted first group of code into a function and gave it some descriptive name that says this will greet the users now let's take the code for picking out the first names so this code block here and put it in a function called print first names because that's what it does right it goes through the bookings and it prints the first names of the people who booked the tickets so i'm gonna cut this whole thing out so here we will call function print first names and right here we're going to create that function with the name again descriptive name print first names again function block and all the code that i copied will go inside if i save again you'll see that we need some values as an input because we don't have them available here so go doesn't know where this bookings variable comes from it's not available inside this function so we have to pass it as a parameter and we're going to define it here bookings is a slice of strings so the type is going to be square brackets and string that's it and if i save this error will disappear now we have to actually call this function otherwise the first names will not be printed out so function call and we have to pass bookings as a parameter that's it we have extracted another block of code or another logic into its own function now let's say we wanted to print the first names actually in the main function so we only want to pick the first names from the bookings slice in this function but the final printing so this line here should actually be done in the main function for whatever reason so instead of printing the first names we want this function to actually just return the first names to the main function so that main can print it itself so instead of this line we want return first names so return keyword as you see the highlight here says that this function is doing some logic and then returning a result of that logic back to the main function and we have an error here because whenever we are returning something from a function we also have to specifically say that in the function definition that we are returning a value of a certain type in our case first names is also a slice of strings so that's what we're returning so note that within those brackets we have the input parameters and outside those brackets we have output parameters with a type of the output we're returning and this print line should go back to the main function and if i save this of course main function doesn't know this variable because we should get that from this function right here and let's actually rename this function now because it now doesn't print the first names it just returns or gets the first names and whenever function actually returns something to us we can save that return value into a variable and let's call this variable first names because that's what we need here equals first names is a result of whatever get first names function gives us and that's it so our function does its thing its logic it gives us a result and then we take that result in the main function like this and do something with it like print it out let's see what else can we extract here another candidate for its own function can be the user input validation so i'm going to take this logic and let's actually create another function called validate user input and again let's fix the indentation like this by now you already know how this works we need to define all the variables that we're using here we need to define them as input parameters so first name which is a string last name also a string email also a string and user tickets which is integer finally or it's actually you int and finally remaining tickets which is also you int and if i save all these errors are gone and we're going to call this function with all the input parameters we defined so we have the first name last name email user tickets and remaining tickets like this however now we don't have these three variables available in the main function anymore that's why we have these errors here because it doesn't recognize these variables and we have errors here as well so we need those three values actually available in the main function so we need to return all three values back to the main function well in most programming languages you cannot do that you cannot return multiple values from a function you can always return just one value but in go you can return any number of values you want from a function which i think is pretty cool because there are many use cases for this and it works the same way as returning just one value we just say return and we just list any values or variables that we want to return like this and of course the same way as with one return value we have to define the types the data types of all the return values in order which we do outside those parentheses and when we have multiple returns we have to also enclose them in its own separate parentheses so within this block we're going to define the data types of these three values which are all boolean true or false values so this is going to be boolean 1 boolean 2 volume 3. so again input values in the first parenthesis input parameters and then in the second one a list of output parameter types and now that we're returning these three values it's time to grab them or collect them outside here and that is also pretty easy we can just list them one by one like ease valid name is valid email is valid ticket number save and there you go now all these three variables are available in the main function so the errors are gone so let's check our code we have these three functions that we created and our main function got smaller and maybe more descriptive now let's also extract the code for getting user input in a function so i'm going to grab this whole code tool here and save it into a separate function and let's call this get user input fix the indentation and as you see get user input function doesn't need any input parameters because we're asking for input from the users so we don't need anything from the main function however inside the main function we need those values because we're doing all the processing based on whatever user entered right so we have to actually return all these input data back to the main so return first name last name email and use the tickets and again we have to specify the types of those right here so first name last name email and user tickets and in the main just like we did right here we're gonna grab those values one by one so we have the first name last name email and user tickets and if i save this you see all the errors are gone because now we have these four values available here as well and finally let's take the code for booking the application actually this whole logic here and also put it in its own function and logically we're going to call this function book ticket and if i save you see a bunch of errors because we don't have these values available here so we need a lot of input parameters for this function so let's define them one by one remaining tickets user tickets bookings which is a slice of strings we have the first name last name email and finally we also need the conference name which is also string and if i save it all looks fine when we call this function in the main so this is where book ticket happens we're going to pass all those defined parameters which is a long list of values now here you may be wondering if i have to pass so many parameters to my function does it make my code cleaner that's a lot of repeated code because we're passing all these same values and parameters to different functions so to reduce this repetition a bit we can define variables that are shared among multiple functions so variables that are accessible both for main and other functions as well without having to pass them around like this so it makes sense to create those variables in a place that lets multiple functions including the main have access to them and these are called package level variables and these are variables defined outside from all the functions so instead of defining these variables inside of the main we're going to take them and instead define them outside on a package level like this and now they're not only accessible to main but also to all the functions in this package now if i save this you see we have two errors and that is because the package level variables cannot be created using this syntax they need the syntax with var keyword so if i save this you see the error is gone we'll do the same here and that's it we can also take the put the constant at the top like this so now as i said we don't have to pass those variables to other functions from main because these functions also have access to them directly so in the grid users function for example we were passing three of these variables as parameters now we don't need this anymore because grid users can access those variables directly so i'm going to delete this and save and we have an error because now the names of the variables have to be exactly what is defined here right so conference name like this conference tickets and that's it we have no errors and no need to pass those values as input parameters again makes the function execution much cleaner we also have the bookings array which is defined on a package level so we don't need to pass that here as well so i'm going to remove this from get first names and remove these here as well again everything works same thing right here validate user input we're passing it remaining tickets as a variable which it doesn't need anymore but it still needs those four variables obviously because they are still created in the main function and not available directly outside so let's go to validate user input and remove this last parameter and finally our book ticket function that has this long list of parameters we can get rid of remaining tickets bookings and conference name as parameters because they are all defined here so remove this one and if i save everything looks fine again now you may be thinking why not define all the variables at the top right here and then make them accessible everywhere in our functions well this would be a bad practice because generally you want to define a variable as locally as possible so basically create a variable where you need it so if you need a variable only inside a specific function or a specific block inside the function then you should define it there so now if we look at our main function you see that the code is way cleaner we have descriptive function names that basically tells us what exactly is happening within the main function we're greeting the users then we're getting their inputs we're validating that input and if everything is valid we're booking the ticket then getting the first names and printing them and if the remaining tickets is zero we just end the program and all this logic that was basically crowding the main function is now encapsulated in its own small functions now let's actually test that everything still works fine and there you go we have the thank you message the ticket number got updated correctly and we have the first names of the bookings printed here so everything works same as before now in addition to just cleaning things up functions have another important purpose which is that same block of code can be reused in many different places in your application by calling the function name just like variables where we define something once and reuse it hundred times so for example if you were hosting 10 conferences at the same time and needed to ask for and validate user input you can reuse that code for all 10 conferences instead of writing that same logic 10 times now we've been working in one single file this whole time so you're maybe asking what if i'm writing a more complex go application with a lot of logic so do i put all the stuff in one go file or how does it work can we create multiple go files that all belong to the same project well remember at the beginning i said that go is organized into packages and the package is a collection of go files which can be one file or several files and we already have one package that we called main which we created and we also have one go file for that package which we called main.go now if our code got larger we can split it into multiple files so for example if we had 10 different conferences for which users could book the tickets on our application we could create own files for each conference booking plus if we had multiple files where we defined bookings for different conferences we might have code that is shared by all these files so we may need the same functionality in all 10 conference bookings for example we might need the same user input validation in all our files so we could have a separate file for such shared functionalities as well and all these files could belong to the same package so to demonstrate that i'm going to create a file here and let's call it helper.go or we can also call it common or shared.go and this can include functions that are helper functions of the main application again as an example we can take user input validation the first thing we need to define here is which package this go file belongs to and we have the main package that we created and we want this file to also belong to that main package so that's one thing we need to define in each file and then we basically just need to put some functionality here or list of functions that we can reference from other files again if i had 10 different files here that all share the functions right here we can basically define them here in helper go and then reference it from everywhere so i'm gonna grab validate user input function from here and i'm going to put it into a helper dot go file so we're basically splitting our code into multiple files of course we need to import the strings package here because we're using it and if i save this everything is error-free in helper.go as well as main.go so basically it is super easy to divide your code up into multiple files that all belong to the same package because we're referencing this validate user input in the main dot go file right here and it knows exactly that this function comes from the helper dot go file now we want to validate that everything works and run our application however if i run my application like this with go run main.go and execute you see that it says validate user input is not defined on line 21 so right here so this function is not defined and that is because we need to now run the application with all the files that belong to that application so now we have main.go in helper dot go so we have to provide both files to go run command and now if i execute everything works again and let's add some invalid input here to make sure the validate user input also works and as you see we have the messages about wrong user input now of course if you have tens of files here in your application it's not very convenient to have to pass them one by one to go run command so as an alternative you can just specify a folder location from which you want to execute the files so all the files in this folder will be executed and dot specifies the current folder which is the booking app so we're telling go to run application with all the files in the current folder and again it works fine so that's going to be a better alternative of course if you have multiple files in your go project so now we have this helper.go file that belongs to the same main package however we could actually organize our application code into multiple packages so in addition to the main package we can have other packages that all belong to the application so what could be a use case for that let's say we have an application that handles booking for 10 different conferences and the booking logic for each conference is almost completely different in that case we could actually create own packages for each of the conference and put the booking logic there and plus let's say they share some common logic like validating user input and that could also be a separate package that all other packages may share so basically these multiple packages helps you organize your code and group the logic in a way that makes sense for your application so this is a way to logically group your code so let's say in our example we wanted to put this helper functionality in its own package and let's call this package also helper when we have multiple packages we should actually create folders for them and then put all the files belonging to that package in that folder so i'm going to create a folder called helper and put the helper.go file in that folder again this helps organize our code and basically visually represent the separation as well now of course we need to make a couple of adjustments for our application to work again the first thing is if we go to the main dot go file right here where the function is being called you see that it says undeclared names because go doesn't know this function anymore it doesn't know where it's coming from and that's why it says undeclared name so while this function was in the same package go was able to find it without a problem but now that we've moved it to another package it is not recognized anymore in the main package and remember at the very beginning i said that whenever we need to use a function from another package in our main package we need to explicitly import that package and then we will be able to use any functions inside that and that applies to the packages that we create ourselves so the first step will be to actually import the helper package in our main package if we want to use any functions defined inside right here now the question here is can we just import it using its name like this helper well just writing the helper the name of the package is not gonna work because go will try to look for a helper package in one of its built-in modules but this is actually our own package so we have to explicitly tell go hey this is actually a package in our application or in our module so remember this go.mod file that we initiated at the beginning this mod file or module file actually defines the name of the module which we called booking dash app which is also an import path for all the packages defined in this module so if we want to import a helper package inside the main package we have to use the booking app the module name before as a path so now we are telling go import the helper package from our booking app module and if we hover you see that it was able to find that package now we just get an error because we're not using it so how do we use a function from another package simply using the package name dot function name just like we've been doing this whole time so helper dot and then name of the function now there is one more thing we need to do for this to work and right now you see that we have an error that says validate user input or the name of the function is not exported by package so what does this mean whenever we want to create a function in a package that can be used in another package we have to explicitly export that function so it can be imported in another package so exporting basically means we want to make this function available for use in other packages and many programming languages have this concept of exporting functions to make it available for use in other places and they all do it in different ways in go the way to export a function is actually pretty easy we just capitalize the name of that function like this and that's it this simple change in the background will actually export the validate user input function so let's save it go back to main and adjust the function name here and you see the error is gone and now we are able to use that function from another package in our main application and you probably also noticed before that whenever we were using a function from an imported package like fmt or strings or whatever we were using that function name with capital letter right so all the fmt package functions start with capital letter we have printf with capital p print ln here we have strings.fields with capital f so that is the same concept right here these are functions that have been exported in these packages and that's why we're able to use them and by the way you can not only export functions from other packages but you can also export variables also by capitalizing the variable name so for example if all the conferences had the same number of tickets available you could define that in this helper package as a variable and then export it simply by using a capitalized variable name and finally we have an error here because remaining tickets variable is not available anymore for this function and that's again because we move this function from a main package and main package right here defines a package level variable called remaining tickets which is only available within the package main that's why it's called package level so it's not visible to other packages again as i said we could export this variable using uppercase in the name but in our case we will just pass the variable as an input parameter so let's do that validate user input and of course we have to also edit in the function specification and remaining tickets is of you int type and that fixes last issue and our application should work again so if i execute the application everything works fine again and one more thing that i want to note here is all the places we have created variables first of all we have created variables within individual functions which made these variables available only within those functions so these are basically what's called local or function level variables we also created variables that were available only within a specific block of code like right here so this names variable it only exists within this for loop so outside that even within the function the variable names does not exist so you couldn't use it outside that for loop it's undeclared then we saw how to define variables on a package level so that multiple functions can access it directly so we define them right here and finally i mentioned that if we have variables that we want to share across packages then we could create what's called global variable using a capitalized variable name and the concept of where we create variables and where we can use them is called variable scope okay so we have split our application into multiple packages and as i said with multiple packages you can organize your code more logically now for the simplicity we're going to revert our example back to helper.go being in a main package and continue with the rest of the demo examples from that state great now we have organized our code a bit we have cleaned it up with functions we have divided our code into multiple files and so on but there is one thing we want to optimize in our application right now whenever user completes a booking we're saving only their full name in the bookings list but the email address and the number of tickets they provided during the booking just get ignored and thrown away we're not saving them but we would like to have that information also saved for each user on the list of bookings maybe to send them information via email in the future or during the event to kind of validate how many tickets they have booked now bookings in our case is a slice which allows us to save a list of string values which are the full names but instead of just a simple string like this we want a data type with multiple key value pairs per user so something like first name [Music] and its value last name and its value email and number of tickets so instead of a list of these type of values we want at least of this kind of data block for each user and the data type that will allow storing multiple key value pairs per user is called a map so a construct a data type that basically lets us save information about user like this is provided by map and map is a common data type in many other programming languages as well so for each user we will have a map with key names like this and their respective values which of course will be different for each user so let's see how we can turn our bookings list from a list of strings to a list of maps first of all let's go to the book ticket function where we're adding users first name and last name to the bookings list and right before that we're going to create a map for a user and as i said map is a data type so just like with any other data type we need to create a variable of an empty map and we're going to call this let's say a user or user data now how do we create a map first of all we have a keyword map and then we have to define types for the key and a value as i said map is a collection of key value pairs and for each one so for the for the keys which are first name last name email etc we have to define what data type they are and we also have to define the data types of the values and of course these two can be different the keys in the map may be strings and the values may be integers but in our case we have strings for both of them however this only defines the type of the map right just like we have a type of a slice right so this is this is a type of a slice we have a type for a map which is this one right here so this is only a type what we actually need to do is create an empty map and we see that in the error as well it says type definition is not an expression so we need an expression which is creating an empty map and to create an empty map we have a built-in function called make if i save now i only get an error that user data is defined but not used so that will give us an empty map so map creation is done as a next step we want to add all the user data we have available to this user data map how do we add data key value pairs to a map very simple actually we have name of the map and the square brackets syntax that you already know from arrays and slices and inside that we have the key name which is first name and the value to that which is the value of the first name variable so that's the first key value pair that we're saving into user data map let's save another key value pair which is last name and again value will be a last name variable which we get from the user input and we have the email which also comes from variable called email so now we have added three key value pairs to user data map so the key names are strings as we defined here and the values are also strings as we defined here and note that you can call these key names whatever you want so this could be a b c it doesn't really matter right but of course you want to have some descriptive names which tells you what this key actually refers to okay now the fourth data we have is number of tickets but the user tickets value is a uint it's not a string right so the value type is not a string and in go specifically as we saw here map can only have the same data type as keys and the same data type for values so we cannot mix different data types as values again specific to go because in many programming languages you can actually have mixed data types in a map just like in a slice where we also have to have just one data type which is again specific for go because in many other programming languages you can actually have mixed data types so what do we do here how do we add the user tickets value in our user data map well an easy way to handle this is to convert the user ticket's view integer to a number character so basically if user bought 30 tickets instead of 30 like this we're gonna have three zero as characters and that will make it a string and this type of conversion there is a built-in function in go called format uiint and this function comes from a package called string convert or scr conf stands for string conversion and this package basically includes different functions for converting strings to and from other data types and one of them is converting uint to string so of course we need to pass in our uiint value so that it can be converted to a string and we do that by using another built-in function called uint64 which is for a uint 64 data type so that's the value we're converting to a string like this and then we have to pass another input parameter here which stands for decimal number base 10. so now you don't need to understand every part of this conversion but shortly explained format unit function takes our u int value which may be anything 1 to 50 and formats it to a string as a decimal number and 10 is for base 10 which represents decimal numbers so another example would be 16 for example that represents hexadecimal numbers so that's what's going on here again no need to go into details here because usually if you need these type of conversions in your code you would either check out the official documentation of go or you will just google it and see the example code for that so you don't have to memorize this kind of conversions so as a result this will actually give us our user tickets in string format and we can then save it into our map and this is going to be a key name for that which we can name whatever we want i'm going to call it number of tickets and that is going to equal to this and of course we shouldn't forget to import the string conversion package like this and everything looks fine cool so now we are creating a map for each user because this book ticket function gets executed every time a new user books a ticket so the map is getting created and all the user data gets saved into that map so now we need to actually take that map with all the user data and add it to the bookings list right now we have a slice of strings as bookings so first we need to make bookings variable into a slice of maps so what i'm going to do is i'm going to copy the type of this map and right here instead of the string type i'm going to set a map type so we're having a list of maps and not anymore a list of strings now this curly braces was used to create an empty list of strings however it doesn't work anymore for maps so we need to actually create an empty slice of maps and the syntax for that is at the beginning again the make function that we use to create a map like this note the comparison between the two make calls so here when we created a map we have a type of the map and we wrap it into make function and that creates an empty map here we're not creating an empty map we're creating an empty list of maps that's why now we have the brackets before the map and when i save this we're going to have an error because this time because it's a list we need to actually define a size or initial size of this empty list and because slices are dynamic this is going to be the initial size and it will expand automatically as we add new values which means the size the initial size can be 1 or even 0 because it will increase anyways when we add new elements so with this syntax we're initializing a list of maps and finally as the last step going back to our book ticket logic we of course want to add instead of adding first name plus last name in our bookings list we want to add user data map and save there you go so append stays the same because it's a slice again but instead of a string we're adding now a map to our list so now we have a bookings list which contains all user information as key value pairs we still have an error in our application which is right here where we are going through the bookings list and grabbing the first names from each element which is logical because in this code we are treating the element of the bookings list as a string and not a map which obviously has changed so we have to change the logic here as well so now each booking elements or the value of this booking variable is a map with the key value pairs for first name last name email and number of tickets so it's actually now easier to extract the first name from the map by simply using the key name which we called first name and that's it so this will give us a value of the first name we don't have to split a string or do anything here and we can also use that directly right here and save and that's it so again in our bookings list we have maps for each user with different data one of them being first name so we can grab the first name value from each map using this syntax and then edit to the first name slice so that fixes the issue and finally as a great feature of go we're reminded that we're no longer using the strings package so we should get rid of it and no more errors in our application so now we can run our application to make sure everything works perfectly plus to also check our changes that we store the complete user data in the bookings let's also print out the bookings list of maps after every booking let's see list of bookings is i forgot the new line and there you go so after the booking we have a list of bookings which is a slice you see with the brackets and inside that we have one map because we just have one booking and this map contains basically these key value pairs for email first name last name and number of tickets divided separated by columns and let's try another one and now our list of bookings has two maps like this and the printing of first names also works fine now let's say we wanted to collect different types of data on users for example we asked for their date of birth which is a date value type or we asked a user to opt in for a newsletter and we would save that information as a boolean data type like is opted in for newsletter we may even want to save lists associated with users like let's say a manager books tickets for her team and we would like to know names of these team members to know who will attend the conference so for this user we can save a list of team members they will bring with them and this would be an array or slice of attendance names if we wanted the team members email addresses in addition then this would even be a slice of maps where each map will hold the name of the attendant and their email address so user entity would have all these data of different data types associated to it we may also have other entities in our application like a conference which will have its own data associated to it like in which cities the conference is held on which dates it is hosted how many people are attending etc again values of mixed data types and as we saw in the previous example maps in go limit values to only one data type that's why we had to do this type conversion to save number of tickets for a user as a string instead of uiint so how can we save mixed data type values for an entity like a user or conference in our go application well for that we can use what's called a struct in go which stands for structure structs or structures let us define key value pairs for an entity like user but with mixed data types so let's see how we can create a struct so right here outside all the functions on the package level we're going to create a struct first of all we have a keyword struct and it's block with curly braces and within the block we define the list of keys like first name last name email and number of tickets like this note that we're not using quotes here and for each key in the struct we also have to define the type of the value right so instead of having one type for all the values we can choose different type for each value so the first name will be a string the last name will be a string email will be a string and number of tickets will be you int again if we had other data types like a boolean for is user opted in for news letter we can basically add them right so we can have mixed data types for the values but our struct is not done yet first we need a name for our struct which in our case can be a user data for example and finally at the beginning we have to create a struct using type keyword like this this actually means that we're creating a custom type in our application which is called user data another very important advantage of structures over maps is that in addition to just being able to specify these mixed data types the structure gives us this custom type like user where we can define exactly what user type should look like so what properties it should have and with map we just have an empty list where we can just put whatever we want so structure allows you to create a predefined structure by listing all the properties that it should have so here we are defining the structure of our user type and that a user has first name last name email and number of tickets and if you know object oriented languages like java struct can be compared to classes in those languages so we're creating a custom data type called user data with these properties associated to it great so now let's go ahead and use our user data structure instead of the map so first of all we're going to change our bookings from a list of maps to a list of user data structures so we're going to grab the map type and we're going to replace it with user data struct type like this nicer syntax everything else stays the same so this line basically now creates or initiates an empty list of user data structs now of course we also have to create the user data struct instead of the map in the book ticket function so let's scroll down to here and the user data instead of creating a map here we're going to create a struct like this the name of the struct and curly braces and inside that we are going to set the values for each property or each field name so first name is going to be the name from the first name variable in this case they're called the same but of course could be different values then we have the last name field of our struct and the value will be from the last name variable email same here and the key name for user tickets like this and the value called user tickets and when setting these values we have to separate each line using a comma so at the end of each line so this will give us a user data object with all the user data so we don't actually need any conversion from you in type to string as well as we don't need these lines here so let's get rid of it and again our code looks a little bit more cleaner and a reminder from go that we don't need the string conversion package anymore so let's remove that as well and finally as the last fix because we still have one issue which is right here getting the first names because now we are accessing the first name with a syntax for map but a booking variable is not a map anymore it's a struct and to get values from struct basically we use a syntax with dot and as i mentioned a big difference of structures of our maps is that it gives you a predefined structure so now when i type dot after a struct element go actually gives me suggestions property names that destruct has and i can just choose one like this but also if i actually misspell a name of the property of a struct go can help me identify this error even before running the application and this is because we have created a real type with a structure in which the go compiler knows the associated properties so as you see when working with structs the syntax is simpler than with maps so our code looks cleaner and less messy awesome so that's basically the final result of our code we're also using just one package here so we can remove the parentheses here and again we can test our application and in the output you see the line where we're printing the list of bookings which is now a list of structs this is how it looks like so we have a slice with square brackets and inside that we have one element which is a struct with a nice short output and again if we add another user booking like this you see one struct and another one now let's say after user books at ticket we want to generate that book ticket and send it to the user per email address that they entered so let's create a function called send ticket that generates a ticket and then sends it per email and we're just going to simulate this logic with a simple code and to simulate generating a ticket we're just going to put together a string that basically says this is a ticket for a certain user so let's use a printf so we're just printing it out and let's say this many tickets for first name last name of the user and let's add them here if i save this of course we need to pass those variables as input parameters right so we can use them in a function so i'm going to define them all here i'm actually just going to copy this and then just add types so we have uint string and another string like this now let's say instead of just printing out this string we wanted to save it into a variable called ticket that we would then send per email and that may be another useful example that you may need in your applications to basically save formatted strings in a variable instead of just printing them out now if i do variable ticket here and save it you see that i get an error because this doesn't give me the formatted string back it just prints it out to the console and it doesn't return string for that we actually have a different function from the format package which is called s print f and if i save this you see that now we just get an error because ticket is declared but not used so this function basically helps you put together a string just like in the formatted output here but instead of printing it out you can save it into a string variable so we have simulated the tick generation and now let's simulate sending it per email in this case we're just going to use a print statement which says sending ticket and this is the ticket to email address and that's an email address so we have the ticket so here we substitute the ticket itself so this string that we put here together and the email address and now we have to add email address also as input parameter so we can use it here and let's do a little bit more formatting so we can see the ticket part really well so i'm just going to do column here and let's print the ticket on a new line like this let's put a new line here as well and i'm also gonna add some visual divider for the ticket sending logic before sending the ticket and afterwards and that's just going to be simple visual divider something that we're just going to notice immediately like this println there you go so this basically just simulates with simple code a logic for generating a ticket and then sending it to email after user booked the ticket so i'm going to take the name of the function and we actually have to call this right so in the main function right after book ticket gets executed we're going to call send ticket and this expects the variables which are actually the same as here right so we have user tickets first name last name email just like we defined it here awesome so our application is ready let's now actually run our application and see that this output gets printed out and there you go so we have 45 tickets remaining which is in the book ticket function and then send ticket gets executed it starts right here and we are saying sending tickets this is the string we put together how many tickets the user bought and the username last name to email address they gave us awesome everything works fine now let's say that generating the ticket and then sending it per email actually takes some time it's not a fast process that we simulated here some data needs to be processed in the background so if we had a real code that really generates a pdf of a ticket and then sends it using an email client to an email address it would actually take some time right it would not be this fast so let's say it would take 10 seconds and we're also going to simulate this 10 second delay using a function called sleep from a time package and in a slip function we're going to say how long it needs to sleep so 10 seconds again the second unit is in the time package and we of course have to import it time and there you go so now whenever this function gets called we're simulating that something happens here for 10 seconds so in this case it's just sleeping and after 10 seconds this code gets executed and we're going to get the summary so the sleep basically just stops the execution of the thread for 10 seconds that's what we're doing so now with this change let's run the application now and see what happens or see how application can handle this kind of time delay so i'm going to clean this up let's run input the data and as you see i didn't get an input enter your last name and if i type something here the application basically is blocked and now you see that after 10 seconds were over this got printed out and now application became responsive again and now it's asking me for inputs for another user right let's do that again and again you see it's stopped here and now whatever i input i don't get a feedback from the application i just have to wait until this here gets printed out or this gets completed so the application is being blocked while this code gets executed and once it's done then we can continue to another booking now if this was an application that should handle multiple bookings of multiple users then this would not be an optimal performance right and that's why we need concurrency in applications and as i mentioned at the beginning the main advantage of goal programming language is the simplicity of coding concurrent applications so we can make our application concurrent in a very easy way in go compared to other languages so what would concurrency mean in this case well our application runs in a single thread right when go starts executing this main function everything that you see here will be executed from start to finish in a single thread which means all code lines get executed one by one in this order in our single threaded application and that means if one of the lines like this one here takes longer the execution in this thread is blocked so the next line gets executed only after this one is done doing its job so this has to wait those 10 seconds until it gets executed but to optimize this instead of just waiting for a certain code line to finish when we know that something takes longer we want to start a separate thread for it and execute this logic in a separate thread so break out of the main thread and do this in its own separate thread so now instead of waiting for 10 seconds to run the next line after the function the application executes it gets to this point it spins off a new thread pushes the code execution there and it immediately continues to the next line so there's no waiting or blocking here very simple concept actually and that would mean in our application that while the ticket is being generated and sent to the user who just booked the ticket we can continue to the next booking for the next user without any interruption when the second user is also done booking her ticket then again the iteration will come here and again it will spin off a new thread to generate the second user's ticket and send it per email and so on so basically if 20 users book the ticket at the same time 20 new threads will be created each one will do its job and once completed the thread will be deleted and this whole time the main application flow will continue without any interruptions all right now that sounds all cool but how do we create those threads and make the code in this function so the centicade function run in that separate thread how do we do that well we just write go in front of it and that's it we just made our application concurrent with a simple go keyword and this keyword basically abstracts away the whole thread creation and cleanup and all these for you so you as a developer don't have to worry about this so now let's actually go and test it i'm going to save it clean up and input our data and now when i click enter i should be immediately prompted for another user's booking so enter and there you go it asks me again for enter your first name so let's continue and while i'm actually typing we see that at some point the ticket creation logic was completed and i see the output here so even though it printed out the text in the middle of my user input it doesn't actually interrupt the application flow so here i have dot com and then continue with user tickets and again i can go on to the next user booking and again at some point the second ticket is done and it gets printed here and the user would be able to basically continue their booking without problems so as you see everything works great and we have improved the performance of our application with a simple change in our code and this means now even if the ticket generation took five times longer or ten times longer the main application flow would be unaffected by that and the users will basically get their tickets per email a little later which is also not an issue and to demonstrate that i'm gonna actually put that timer to 50 seconds instead of 10 and let's execute again so basically i have simulated booking for three different users the ticket for the first user is not done yet but we can keep booking new tickets and at some point after the 50 seconds are over you see the output for the first user and the second user and finally for the third user so our application stays responsive no matter how long this code actually takes to execute now let's see one more thing about concurrency in our applications let's say we did not have a for loop here that keeps on asking for the new booking which means once the booking is done the main application would exit there is no next iteration here so i'm going to remove this for loop and save it we don't need a break statement because there is no loop so basically our application only allows for one booking so let's run our application and see what happens with the booking logic so we entered our data the summary got printed out thank you message how many tickets are left and the first names but there is no ticket generation output here so all the code in here send ticket that prints out this three lines we don't see them in the output because they never got executed so the application exited before this function was done and this means that the main thread does not wait for any additional threads to complete or even start when the main thread is done the application is done as well so whatever is happening in the other threads are basically getting terminated and ignored so how can we fix this because obviously we want to send the user their ticket right well for that we need to tell the main thread that it needs to wait until this thread is done doing its job and for that first we need to create what's called a weight group so outside the main function right here we're going to create a weight group with curly braces and this comes from a sync package and we can then save the result into a variable called wg or weight group and of course we need to import the sync package and there you go and weight group has three functions which we can call using this variable so on wg right before we spin off a new thread we're going to call the first function which is called ed and this function adds a number of threads that the main thread should wait for and should be executed before creating a new thread and in our case we have one new thread that we are adding so we're gonna put one here so if you had another go do something else function here then you would put two another function that we have the second function of weight group is called weight and it needs to be executed at the end of the main thread so as a last line of the code we're going to do weight and this basically waits for all the threads that were added right here to be done doing its job before the application can exit so this just waits until this one is done and the third function is called done which gets executed in the function that runs in a separate thread so incenticate and at the end of the logic when everything is done we're going to call weight group done so done function removes the thread that we added right here from the waiting list it's basically saying to the weight group i'm done executing so the main thread doesn't have to wait for me anymore so the add function is increasing the counter of threads that the application should wait for and done is decreasing that counter so when the counter is zero which means the main thread has no threads to wait for it can exit the application so this doesn't have to wait anymore so now with these code changes let's run our application again and we should see the ticket being printed out before the application exits so the summary got already printed out now it's just waiting as you see it's not exiting it is basically waiting for those 50 seconds to be over and then we'll execute these lines of code and you see the output of sent ticket so this time the application actually waited for this separate thread to be done executing its logic and once this was printed out as you see the application exited now you may be thinking you can surely implement concurrency in other languages like java right which is true but in other languages that support concurrency we have two differences with go first of all writing code for concurrency in those languages is way more complex and you have more overhead for the initial configuration and second creating threads is more expensive which means it takes longer to spin off a new thread and it also needs more memory space allocated to it now what is the reason for these differences or what does go actually do better or more efficiently well in go when we create a thread go actually spins off what's called a green thread green thread in go is an abstraction of an actual thread which is an operating system thread and it's called a go routine so with gold keyword we're actually creating go routines so in go we are only interacting with these high level goal routines instead of the low-level operating system threats and an advantage of working with this threat abstraction is that first of all it's cheaper to create it's more lightweight and takes little memory space so each time you create a thread you actually have way less overhead and that means you can easily create and use thousands or tens of thousands of threads pretty fast which in other languages is normally not possible without affecting the application performance so in comparison other programming languages like java that i mentioned use operating system threads which again need more memory space more time to create and that's why in these languages sometimes we have concepts like thread pooling to optimize working with threats and one last difference is that in other programming languages threats do not have an easy communication medium or way to talk to each other in contrast go routines has a concept of channels which is a built-in functionality which allows easy and safe communication between the go routines and this is a functionality that helps you handle concurrency issues which are issues that may occur when threats have shared data or are dependent on each other now we're not covering this in this beginner tutorial because it's a more advanced topic but it's an important one so i will include it in my upcoming go course congratulations you made it till the end so what do you think about go have you already used it in one of your projects share your thoughts in the comments section of the video now in this beginner course we built a simple cli application without persistence but learned a lot of the main goal concepts but of course in real life this would be a web application with a ui and a database connected to it where multiple users can book their tickets at the same time and the bookings will be persisted in a database so if you want to take your go skills to another level and want to learn more advanced concepts in go i'm actually going to create a go course where you will learn to build exactly this kind of application with go if you want to be notified when the course is out then check out the video description for a sign up link or if you're watching this video by the time the course is already released then you will find a link to the course itself and with that thank you for watching and see you in the next video
Info
Channel: TechWorld with Nana
Views: 14,213
Rating: undefined out of 5
Keywords: golang, programming, go tutorial, golang tutorial, golang for beginners, learn golang, go for beginners, go tutorial for beginners, golang tutorial for beginners, what is golang used for, golang concurrency, go concurrency tutorial, goroutines, goroutines vs threads, golang struct, golang slice, why golang, golang introduction, techworld with nana, golang vs python, why learn golang, what is golang good for, go lang, go programming, go, go package, go crash course
Id: yyUHQIec83I
Channel Id: undefined
Length: 204min 58sec (12298 seconds)
Published: Mon Dec 20 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.