Getting Started with Go Full Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] the point of this first module is to uh to talk about well really four things first thing is we want to talk about go why it's good why it's unique right we want to motivate you just tell you why do you need to even learn this in the first place as compared to existing languages because there are many right so we'll talk about that then we'll have you start using go so this specifically means installing the go environment and compiling your first program you need to get through that before you can go on with the rest of the course so we'll uh sort of walk you through the installation process and show you how to just compile a program and see that it works as a sanity check for the whole setup then we'll start talking about the code organization the recommended code organization so workspace so how you know how you define your workspace how it should be organized how go code is organized into packages to allow you to share so a big point of go is sharing with other people right because if you want to think about any real software you write it's always big right you work with other people and they're almost never just you alone and so you got to share and packages help to make that easy and to organize the code so you can trade your code with other people then at the end of this module we'll start talking about variables uh start talking about the language itself so the variables what types there are and how did you do scoping how variable scoping happens uh how you can determine how you basically resolve the value of a variable depending on where it occurs and where it's defined [Music] so why should you learn go what's unique and good about the go language i'll go over some of the highlights of that different people have different opinions but there are certain features that are pretty uniformly understood as being advantages advantages of the go language so uh some of the advantages of go first uh runs fast okay that's always a good thing and i'll talk a little bit more detail in these slides about why it runs fast and faster than what right it doesn't run faster than everything but it runs fast in a lot of things and we'll talk about why garbage collection that's another feature that in similar languages meaning languages that run fast like go does they don't have garbage collection so garbage collection is a really useful feature i'll describe what that is simpler objects now this could be an advantage a disadvantage but the idea is that go is essentially object oriented although some might disagree but it has this concept of objects and these objects are generally uh the object orientation is a little uh simplified as compared to other languages so this is good it makes it easier to code you don't have to use these complicated features of course you never had to use them anyway but it makes it faster and simpler to use so i now somebody might argue that look these features are useful features i wanted them okay but go is actually a simpler object-oriented implementation than you would see in other languages like say c plus and another feature of go is that it has concurrency efficient concurrency implementation built into language so there are a lot of these concurrency primitives that are built into the language and that are efficiently implemented and we'll talk about those so to start off with let's go into that code running fast thing and tell you why that is the case and to talk about that we've got to talk about a little bit about languages in general differences between languages so i've got these three very broad categories of languages for machines so one is machine language next is assembly language next is high level language right now that's a really big category but let me explain machine language you start off with that is the the lowest level language and it's directly executed on the cpu on the processor so the machine language instructions are very very straightforward and simple you know add multiply you know add might add to register contents put the result in another register something like that very small steps each machine language instruction now and these this runs directly on the processor so uh so there's that there's assembly language and assembly language is basically machine language almost a one-to-one mapping to machine language so in machine language say you had an ad instruction that might be represented as a sequence of zeros and ones one one one one zero zero that might be an ad you know opcode for an ad so in assembly language you would use the word add right so it maps one to one to the machine language equivalent but you can read it because it's english now it's concise english little and i would argue it's hard to read but it's english and mnemonic so a human could read that and could write that if you wanted to and people do sometimes if you want something to run really really fast then and really efficiently then you'll write it directly in assembly language you know that's outside of the scope of this class that's hardcore i would call it that is not something we're going to really cover in this class but sometimes you do write directly in assembly language so there's assembly machine and assembly and assembly language is basically a one-to-one mapping to machine language not completely but very close so fundamentally they're the same complexity they're the same language but assembly language is easier to read now as high-level languages that's everything else okay that's a broad category a high-level language is a language that essentially humans commonly use to program in they are much easier to use than assembly language or machine language they provide you with lots of abstractions that any programmer would be used to for instance variables right assembly language and machine language do not have variables they have memory and you can put stuff in it take stuff out right and there's no idea of a type or anything like that in assembly language machine language but high-level languages provide that to you right if statements now assembly language machine language they have conditional branches and so on but these are generally much harder to use than your standard if statement that you would see in any normal high-level language or loops or for loops things like this you can create these things in assembly and machine language but they are harder to write than they would be in a high-level language so high-level languages are basically everything that most people program in so uh one thing so you can imagine these different categories now the languages that we're talking about go go is of course a high level language in this set of lists in this three categories it would be considered high level and remember that term high level is subjective okay but i'll call it high level so all software what i have uh highlighted in the slide all software needs to be translated into the machine language of the processor to be executed so what that means is that if you've got a processor of some kind some i7 or whatever processor you're working with that processor does not know c or java or python or go or c plus plus or any of those right all it knows is its own machine language uh say x86 machine language if it's an intel based processor right or an amd or something like that so it knows that machine language so in order for the code to execute on the processor it has to be first translated into the machine language of the processor so uh even if it's c python java whatever it is has to be translated so there is this software translation step that has to go on okay now this translation step it can go on in one of roughly two ways it can be uh compiled there can be a compilation or interpretation okay now compile a compiled language is a language where the translation from the high level language to the machine code happens one time before you uh execute the code before you deploy the code happens one time okay so like in c c plus plus go java partially there's a compiler and you compile the code so somebody writes the source code they compile it and then they execute it and they execute the compiled executable right the compiled executable is basically machine language code plus other stuff but it's basically machine language code so the idea behind a compiled compile language is the key thing we want to bring out anyway is the fact that this translation occurs once uh it doesn't occur while you're running the code right it happens before you run the code and then when you run the code you are just running the machine language instructions directly because they're already compiled into machine language by the compiler so the other way to do this is interpreted interpretation an interpreted language what happens is instructions are translated while the code is executed so if you got um so so what happens is it happens it adds time to the execution right because every time you see an instruction and say python that code that instruction has to be translated into machine code on the fly and that takes a certain amount of time just to do that translation so in addition to actually executing the instruction you've got to do the translation from the instruction into the equivalent machine code so that slows you down so the translation occurs every time you run the python code say or java right the java byte code i put java as partially in both categories because java java has uh it's compiled but it generates what's called bytecode not actual machine code and then the bytecode has to be interpreted at runtime so there's an interpreter also the java virtual machine but these interpreted languages require an interpreter to be executing while you're running your code because it has to be doing this translation as you execute the code and so that slows you down now uh there's this trade-off between compile code and interpreted code the first level of this trade-off you could one big difference you can see is that compile code is generally faster to execute that's because you don't have to do the translation every time you run the code so it's going to be faster now there are people who would argue the opposite but generally compile code is a lot faster now on the other hand though interpreters make coding easier so the the thing about interpreters is that the interpreter itself that program that is doing the translation of your code it can help you it can handle things that you as a programmer don't want to handle for instance i in python i don't have to declare my variable types i can just start using a variable and the interpreter will say it looks like he's using it as an integer and make it an integer right so that's something that the programmer doesn't have to think about another thing that interpreters commonly have often have is memory management in fact almost always they have this they can manage their memory and by that i mean getting rid of variables and other pieces of data when you're not using them so when you use a variable that variable has to go into memory somewhere and that memory if you keep making variables and using a memory space you will eventually run out of memory things will slow down you'll run out of memory so you have to manage your memory that is when you're done using an object you want to get rid of that uh deallocated from memory and that happens automatically in an interpreted language so the interpreter handles that so that's a good thing about interpreters so go is a good compromise between this compiled and interpreted type of language it's a compiled language but it has some of the features some of the good features of interpreted language specifically it has garbage collection so garbage collection is the automatic memory management that i'm talking about so this memory management you know uh where should memory be allocated so i say i need a variable x where should it put it in memory what type of memory should i put it in uh we'll talk about that a little bit later but also when when am i done with that memory right because when you're done with the memory you can get rid of the memory you don't have to use it anymore you can use it for something else so that's what i talk about memory management that's what i mean and this happens automatically the garbage collector can figure that out it says oh it looks like this this program is done with variable x i will free that memory now and that happens automatically manual memory management is hard okay and you know this is if you've ever done c or something like this you know this uh deallocation deallocate memory too early if you stop using it too early then you'll have false memory access because you still need it so you'll use the memory that's already allocated and errors crop up because of that also if you deallocated too late then you're wasting memory you can have what's called a memory leak where you're you have more and more memory that's not actually being used but it's being blocked up because your machine thinks it's being used right so memory management manually is very difficult and it there are lots of errors security errors too uh so go has a garbage collection package included uh garbage connection garbage collection code included so when it compiles your code it also compiles garbage collection into your code automatically and this is typically only done by interpreters so this is a compiled language that actually has garbage collection which is a really good feature now downside is that it slows down the execution a bit but it's an efficient garbage collector so it doesn't slow it down much and you get a lot of advantage out of having this automatic garbage collection [Music] so go language is object oriented but let's say weekly object oriented so what i mean by that is that it implements objects but uh maybe they have fewer features than you would see in another object-oriented language like python or java or c-plus plus something like that so uh so we're gonna go through i'm just going to summarize what object-oriented languages are uh what object-oriented programming is very briefly and just so i can highlight some of the differences in goes implementation so object-oriented programming is it's really for code organization in my mind is for code organization so you organize your code by encapsulating your code you group together data and functions that are related to each other so uh this is essentially what a type is right so and what object-oriented programming lets you do is essentially create a user-defined type one that's specific for whatever application it is that you're building right so typical types you have integers floats that sort of thing those are generic right you can use those in any kind of program but when you're making a specific application you might like to have a type that is specific to that application domain and you can create that uh object-oriented program allows you to create that so if you think about a type your standard type like an integer each integer it has data right the number the value of the number and then it has functions functions that you can apply to the data so you can apply addition subtraction multiplication that sort of thing so a type has data and has a set of functions that you can apply to the data so uh object-oriented programming is the same idea you are creating types but they are more complicated they can be more complicated and they are specific to your application as an example you might have let's say you're making an application and it's going to do geometry some kind of geometric operations in three dimensions so uh many of the functions that you're going to work that you're going to write are going to operate on points right you're going to have this idea of points because you're doing 3d geometry and each point is going to have some data associated with it specifically you know x and y and z coordinates maybe you want to put other data in there but at least you're going to have that xyz coordinates because in 3d also points are going to have a set of functions a set of functions that you can use to operate on on points so uh distance from origin distance to origin right maybe every point has a distance to its origin you can have a function that that computes that uh quadrant it tells you what quadrant maybe it returns what quadrant the the point is in right something like this uh there are a lot of functions that you can imagine that work on points so if i think about this idea of points i got a bunch of data that i want all related together so i want the x and the y and the z variables for a particular point i want them to be somehow associated together also i like these functions that operate on points to be associated with that too so in typical object oriented languages you have this idea of a class and uh if now i should know right now go does not use this term class okay but i bring it up because it's used in in other object-oriented languages and so people might be familiar with this idea so this class it defines that maybe i'd make a point class and the class defines all the data that would be inside a point so x and y and z maybe they're all floating point values something like that and the class would define all the functions that you would have that are associated with points distance to origin quadrant and so on so that would be the class and then an object is an instant an instantiation of the class so i can make my point class but then i might have many different actual points with actual data values inside so if i have a triangle right i've got three points with three sets of x and y and z values so i might have this point class that's sort of a general template of what what a point should have but then the point objects my three-point object will have actual values for x and y and z and so on so uh that's the idea that's the terminology that you normally see used classes and objects which are instances of that class so different languages have this java it's very popular java python c plus plus and so on now go we don't use this term class instead they use structs now strucks actually this goes back to c and probably before that but the idea of a struct is a struct is just uh just the data so the different types of data that you want to associate together so like with our point class you'd have a point struct and it would have an x and a y and a z maybe they're all three floating points right so just the data related together but also you can associate methods or functions with those structs so the struct ends up being like what you would call a class in a normal object-oriented language so you got these structs that have some data some fields of data associated with them plus some methods that you want to define now goes implementation of structs is simplified compared to compared to traditional implementation of classes so you don't have inheritance you don't have constructors and you don't have generics none of those now this one can argue makes it easier to code also it makes it efficient to run so it typically runs faster but it can make it easier to code unless you like those features now if you like inheritance and generics and constructors then then you can see this is a disadvantage but go is different than it has objects but is different than uh traditional object-oriented implementation and sort of a leaner object or implementation [Music] one of the big advantages of go is this implementation of concurrency uh so we'll talk a little bit right now about concurrency what it is and why it's useful and how go implements it uh how there are built-in constructs in the language that make it easy to to use concurrency so i'm going to start by talking about performance limitations of computers the reason for this is because a lot of the motivation for concurrency comes from comes from the the uh the need for speed okay a lot of the motivation not all but a lot of it does uh so uh so that's why i'm gonna sort of introduce these performance limits on machines and how concurrency can help you get around these performance limitations so uh moore's law so just to summarize you've probably heard of this law but in case you have not moore's law it basically says that the number of transistors on a chip doubles every 18 months now this used to be the case it is not the case anymore recently uh that has changed but this used to be the case and so because of this this doubling of transistors what happened would be uh things with machines would speed up just because the transistors got were smaller and they would they would be closer to each other you could increase increase the clock rate and so clock rates would just increase increase increase i remember when i was in school which was a while ago uh you know you'd buy a machine and seriously a few months later there'd be another machine same price it was faster and it was frustrating okay so these clock rates were just going up and up and up because the number transistors were just increasing now performance that then that was great right and in fact what that meant was that uh you know i'm a hardware person mostly my background is a lot of hardware and so i've always felt like software designers programmers were would get lazy right they'd write code and it didn't have to be particularly efficient in terms of memory in terms of speed because they knew that pretty soon hardware people would you know double the number of transistors and fix all their problems for them okay so that's how it used to be but that is not happening anymore because mosul had to slow down uh there are several reasons why probably the biggest would be the power consumption and therefore temperature constraints so when you pack these transistors on to uh onto a chip they generate heat every time they switch they consume power which generates heat and if you keep increasing the clock rate then they switch zero to one zero to one more frequently higher rate and they create more heat and the chip will physically melt okay so if you've ever opened up a machine you see they got fans blown over the chip in fact usually when you open up a box you see on the box some big heatsink big gnarly looking piece of metal that's actually attached to the processor that's just to distribute heat so the air blows over it the fan blows over it and distributes the heat so it doesn't melt so this is air cooling right and we are basically at the limits of air cooling air cooling can only remove so much heat per unit time and so if you get if you clock these things much faster with this density of transistors you're going to melt the thing so you can't keep increasing the clock rates so that's a it's a performance limit that's happening with machines the clock rates are not going up as fast as quickly as they used to go up over time so uh how do you you know get in performance improvement even though you can't just crank up the clock so one way to do this is to use parallelism so this is uh typically implemented it's simple in a number of ways but you see this as an increasing number of cores on chips this is one way that you see it right so you got quad-core machines these are common right they have four copies of the core on there and you get more right heck if you go to a gpu that thing might have a thousand a thousand processor cores all in the in a massive array right so these cores the number of cores on the processor increases over time and that helps you because you can perform multiple tasks at the same time potentially not always but sometimes if you got four chords you can do four things at once right and that can improve your speed you can get things done faster now it doesn't necessarily improve your latency but your throughput will improve potentially so difficulties with implementing parallelism there are many uh but programming wise there are difficulties so for instance when do the tasks start and when do they stop a programmer has to decide this when you know for tasks these tasks are not completely independent you know so what happens when one task needs to get data that's generated by another task right how does this data transfer occur also if you've got multiple tasks running at the same time you know do these tests conflict in memory right they they should not you don't want one task to write to its variable a and that overrides variable b in another task right so these are all problems that happen when you have concurrent execution going on because even if you got multiple cores you know you got to worry about the memories right are they sharing memories right do they have separate memories this is all you know features of hardware but the programmer has to often be aware of these things and it's hard so writing this type of code code that where that can execute in parallel can be difficult so incomes concurrent programming concurrency is the management of multiple tasks at the same time so when i say at the same time they might not actually be executing at the same time maybe they're executing on a single core processor right so they're not actually executing at the same time but they are alive at the same time so they could be executing at the same time if you had the resource but and they need to be sort of going on at the same time so maybe one is pause while the other one's running but they are all alive at the same time and need to be handled at least from the user's perspective at the same time so this is key for large systems there are big systems have many things many pieces going on and they're not all executing sequentially you know you you want them you want to be able to consider you know 20 things at one time right now maybe they're not actually executing at the same time but they you want to be you would like to have the possibility of executing them in parallel if at all possible just for speed right so uh concurrent programming it enables parallelism right so if you can write program code write code so that all these tasks can be alive multiple tasks can be alive and communicating at the same time then if you have the resources the parallel resources multiple cores multiple memory stuff like this then you can map them onto those parallel resources and get parallelism okay so you need to you can't just take a regular piece of code and say okay i'm gonna run it on five cores that won't work you have to the program has to decide how to partition this code i want this running on one core this on another i want this data here this data there and so on so that's what concurrent programming is about the program is making these decisions that allow things to run in parallel if parallel if the hardware exists so uh that includes concur programming includes several things uh we'll go into more depth and later in the in the in the concentration but specialization rather but uh management of task execution so window test starts and stops how do two tests communicate send data back and forth share memory if they share memory uh and how do they synchronize so there are there are times where one task has to do something before the next guest can start so there are times where two tasks can't be executed completely in parallel there has to be some sequential behavior you know this test can't start until this test ends and so on so that's synchronization and you have to be able to manage that inside your programming language you have to the program basically has to say uh express inside the code where synchronization needs to occur and where it doesn't so that's what concurrent programming is and it is important if you want to be able to exploit parallelism when it exists so concurrency and go so basically the thing about go is a go has a lot of concurrency primitives built in to the language and implement it efficiently so go routines each one of these go routines represents a concurrent task basically a thread uh channels are used for concur for communication between concurrent tasks and select is used to enable synchronization uh these are just a high level basic keywords that you can use but we'll talk more about these later on uh in the specialization but concurrency having concurrency built into the language and having efficient implementation is advantageous if you're doing concurrent programming which more and more especially with all the cores that exist in processes these days is becoming more and more important [Music] we'll talk right now about how you download and install the go tools just to get you started running a program right now we'll uh we'll talk about the download process and then next i'll go through actually doing it uh showing you sort of how to compile your first program but right here just talk about installing which is fairly straightforward so first thing you're going to do is go to golang.org and this is a snippet of the the page when you go there uh this isn't the whole page i had to fit it on the slide but this is what it basically looks like at least right now it does that can change over time of course you can see the gopher so that will go for that you'll see that gopher icon over and over again uh gopher's you know the i don't know the mascot of the go programming language like unix you got demons right so go you have the go gopher but the main thing to look at here is that button down there that says download go so that's the first thing you're going to click on you're going to say download go you click on that and as long as you look at this on the left side when you go to the web page you'll see the whole screen you can i've only i've cut it off here but on the left side you can see uh there's a yellow box there where you can type in go code and click on the run button it'll compile and run it so it'll compile it remotely and run it remotely we're not going to use that instead we're going to download the compiler we're going to download go download to your machine locally and you'll be doing it locally but if you want to just fool around you could type in there type some go program in there click run and it would actually execute it so what we're doing though is we're going to click download go to download the the tools now when you do that you come to page looks like this now again i've only i'm only showing a part of the page there's more below it and to the right basically when you download go you can download the pre-compiled versions for different platforms they've got windows and linux and mac os and you can also download source if you want to and you can compile all of go from scratch this whole tools chain from scratch if you wanted to we will not be doing that uh that is pain we won't be doing that but i know that you could it is open source and all the source is right there for download if you want it so i'm going to be doing this on a windows machine although you could be doing it on a linux or mac os machine either way so if so go for the featured downloads they make it pretty easy for windows you pick that msi file that they've got highlighted right there basically what you want is the newest stable pre-compiled version uh don't go for they don't i don't see on unstable ones on here but you know i would i recommend the stable but it's up to you anyway you go for a new version uh click the featured one and you download msi now once you get that oh and remember there can be if you have an antivirus on your machine it can pop up and worry about this and complain uh but just say okay and then once you start running it it'll start a wizard now you've seen these installation wizards and this is sort of a standard installation wizard just obey the wizard and click next next and it'll ask you where you want to install the tool what directory you want it in and so on the default locations were fine with me but that of course is up to you [Music] right now we're going to talk about how code is organized in go uh first we'll start with a workspace so there's this idea of a workspace and it's basically a directory where your go stuff will go so you go files you go source files and other files will go in this workspace directory and typically there is a actually a hierarchy of directories within your workspace where you will store the different types of go files that you're working with now uh the reason why we're doing this why would why we why the go language defines this hierarchy of directories is because common organization is good for sharing so a big motivation behind go the go language is to um is for people to work together easily so remember that when you're programming uh not necessarily in this class in this class you know you're working on learning the language uh the different aspects of the language but when you get outside and you're working in a company or something like this it's never one person alone it's always a big group right you're working with people all over the place and they have to be able to work with your code look at your code merge it with their code link it to their code that sort of thing so there's always the sharing going on maybe you want to upload to github and have a communal group of people working on code together so for that it is nice to have a common standardized organization of your files right it makes it easier to share because then everybody knows where everything is tools know where things are stuff like that so inside your workspace directory what is recommended are these three subdirectories the source directory it contains the source files your source code your go code package directory contains packages the other packages that you're going to link in that you need and then the bin directory that contains all your executables your compiled executables now the programmer typically has one workspace for many projects so i typically use my one workspace directory and i have i can have you know 20 projects 20 different go projects i'm working on in the same workspace directory that's common you don't have to do that but that's common so uh one thing to remember about these uh these this directory hierarchy is that it's recommended but it's not enforced okay so this idea of having the source subdirectory in the bin subdirectory in the packet subdirectory that's not you know it's not enforced so for instance you can have an executable in the source directory if you want it is not neat and it's hard for people to share but it's going to run you can compile it and put it anywhere you want and run the executable right so it's not enforced it's just uh this is a recommendation to make it easier to share with other people so the workspace directory you do have this one workspace directory though and this workspace directory is defined by the go path environment variable now the gopath environment variable depends on what um you know how you set environment variables is going to depend on your operating system uh in normally what happens is like on my windows machine but it should happen on a linux and an os osx machine too is that the gopath directory is set for you automatically by uh but during the installation process so that wizard that install wizard it should define the go path environment variable and certainly on a on a windows machine the default directory where it sticks it where it puts it is c colon slash uses less your name so for me slash user slash ian go you know it sets that as your gop as your uh your workspace directory now i noticed that when i installed everything that was my go path that was my go path uh what you see up there you use slash e and slash go but it actually didn't create a go directory so there was slash user slash ian i had to create the go directory myself which is fine but i had to make that directory uh and put my stuff in there but understand that that's the default workspace you can change that you can go to your go path environment variable and change your environment variable in your operating system if you want to but for now i'm just assuming that we're using the default go path so the go tools all assume that the code is inside the go path somewhere now there's this other concept of packages your code is organized into packages a package is a group of related source code files each package can be imported by other packages so this is the use for this the main use for this is when you're working with other people other groups of people in other places you write all your code in one package they write all their code in another package and then if you need to use their code you can use their code you can import their their package so actually i have so it's good for software reuse that's the the main goal and uh the first line of the file names the package so what i'm showing here in the picture you can see these two pink boxes up here these are two packages that are defined and you can see the first line of so those are two different files two different source code files and uh and you can see the package names are listed at the top package package right and there's a bunch of code in there and they're all in the they're associated with that package name then in blue i have some other piece of code uh in a different source file and it needs to use the packages from the other two uh people right so i have an import statement at the top of my of my blue file and i import the i give the package names that i want to import so i can use these other two packages in my code if i want to so this is how packages get connected to each other uh and it's very convenient if you're working with somebody remotely or somewhere else they you can it's a sort of a clean separation of the code now there always has to be one package called main and that's where execution starts so there's got to be one package called main and you'll note that in the code that we're working on in this course we're just we just have one package and it is called main okay because we're not making such big code that you know where you have different groups of people working together with different packages right now we're focusing we're just writing one package called main but there must be one package called main and when you build the main package when you compile it it makes an executable of that so note that when you pat build another package on the non-main packages then it doesn't make an executable for those right it or not uh not a running executable because it's not going to be executed directly it'll be incorporated into some other package but the main package that's what's going to be run so when you compile that when you build it bill slash compile you get an executable file so the main package needs to have a function called main and main is where code execution starts so you can see the example code right here it's just just printing hello world we say package main uh import format so that is that import right there is importing a package format is not a package that i wrote format is one of the packages that comes with the go tool so when you download the go tools you get all these standard packages including format and the format package has a lot of functions in it we'll talk more about it later but one of the functions that has this print statement so printf is included in the format package so we have to import that package and then we make our function main and in there it just says format dot printf hello world so pretty straightforward [Music] so we're going to talk about the go to a little bit just overview it really it has a lot of features and we'll get to those over in different courses actually during the specialization uh we'll talk about a little bit of it now but let's start off with import so just to restate what import does it's a keyword and it's used to access other packages okay now for the most part the packages that we're going to be importing will be the built-in packages the ones that come with the go language uh to implement different functions that we're going to use in the course so uh for instance right now like right off the start we're gonna use this format package fmt and it has a printf statement built into it and we use it for printing things now what happens is when you do an import the uh the go tool when you say when it does a build it has to find the imported packages so it searches through the directory specified by the go root and the go path environment variables so if you keep everything inside your go path and you go root so inside your workspace it'll find them uh if you decide you want to import some package from some other place and maybe it's installed in a different directory something like that then you're going to have to change your go path and go root uh paths you're gonna have to increa increase them change the path change the environment variables so that it can find them but that won't be a problem for basically the majority of this course right we're not doing that but i'm saying in the future when you're working with really big code you might need to alter these environment variables in order to be able to find the the packages that you're looking for so the go tool uh go when you download go you get this go tool and it's a it's a general tool used to manage ghost source code there are many commands a bunch of different commands that you can use the go tool to do the first one is going to be go build so that is just compiling the program right the arguments to go build you can have no arguments in which case it just compiles a go file in the local directory but you can give it a bunch of packages a bunch of package names or a bunch of go files that you want to build you can give that as the arguments to this go build command and it'll go build whatever you tell it to build uh or you can just say go build that's what i would actually that's what i did in the in the demo i just said go build and i was already in the directory where i had my my main package and so it just compiled that so it creates an executable for the main package and the executable has the same name as the first dot go file so if you're just using one dot go file you're just going to get that as a name the exe suffix is what you're going to see for executables in windows in general right so you'll expect to see it.exe and the executable and that should be in the directory where you did the the build if you give it no other arguments it'll just place it in the same directory now there are tons of arguments to these commands that i'm not really going to go through but you can have arguments where you can tell it to build and put the executable in a different directory and so on i'm not going to do that right now we'll finesse that stuff later so some of the other go tool commands just go through these a little bit go doc go doc prints documentation for a package now we'll we'll go over this later uh but you have to as a programmer you have to put the documentation in your package and go doc will just pull it out of all your packages and print it go format that format source code files so we're not going to get heavily into this but if you program it all you must have heard arguments about oh you need this type of indentation and stuff like this uh so this go format will just indent it the way it should be done okay it'll you just give it the source code file and it'll indent it right to get past all those arguments right there's a standard indentation you don't have to use it right remember the indentation isn't forced on you this isn't python or something like that you don't have to but go format will do it for you so why not go get downloads packages and install them so if you want to get new packages to do interesting things that aren't standard default packages you can say go get and give the name of the package it'll go online find the package download it uh go list lists install all the installed packages go run compiles the go file and it runs the executable so if you just say go build that compiles it and does not execute it but go run go run actually compiles it and then executes the the executable in the end uh or if it's already compiled it'll just run the executable now you don't need go run you can like in my demo i think i did a go build to get the executable i think it was called hello.exa and then i just typed hello.exe at the command line and it executed it right so i didn't have to use go run in order to run the executable but you can and uh go test actually the last course the fourth course in this specialization is actually about testing and we'll get to that then go test it runs tests uh and it looks basically have a bunch of test files uh that end with this underscore test.go and you can run these tests using the ego test command but we'll cover that later [Music] so now we're going to start talking a little bit about the go language we'll broach the topic of variables and talk a little bit about those variables are in every high level language and we'll just see how go implements it a lot of this is very similar to what you've seen in other languages some things are a little bit different so first there's naming every you need names names for variables for functions you need names to refer to things in your code so names for variables and things like that they need to start with a letter they can have any number of letters and digits and underscores they are case sensitive and go and you can't use keywords uh there's a list of keywords you can google these or look them up but if case package all the different keywords the language you can't uh you can't use those as the names so variables variables are basically data stored in memory somewhere and they every variable has to have a name and a type so all variables have to have a declaration that specifies the name and the type of the variable so there's a very uh so here's a really simple variable declaration uh just says var x int so var is the key word for a declaration of a variable after that i have the name so my name variable is called x and then after that i have the type var x int that's it that's a declaration of this variable x says it's an integer and the machine the compiler needs to know what type of variable it is what what the type is so it knows how much space to allocate what operations to perform that type of thing you can declare many on the same line if you want to uh just comma separated so var x comma y int and you can do that as much as you want so variables have types a type defines the values that a variable can take and the operations that can be performed on that variable so for instance uh common types basic types integer floating point strings integers the data the variables the values that they can take are only integral values right they're integers and the operations you can perform or integer arithmetic you know plus minus times that sort of thing uh and there are a set of other ones we'll talk about them in a little more detail floating point those uh the data that they can have the variable values they can have are fractional right decimal values and there you have a set of operations uh arithmetic operations actually they look superficially the same as the integer operations plus times divide but they may actually be implemented with different hardware right because a floating point division say is significantly more complicated than an energy division so there's oftentimes there's special hardware just for floating point divide and things like this we don't have to know that as programmers but the machine has to know which operation to map it to then uh strings so strings they're a sequence of bytes represented in unicode and we'll get into that later but uh it's a sequence of bytes that's the type of data the values they can take on and then the operations you can perform on strings there are many of them uh string comparison string search you know concatenation all sorts of operations that you can you can perform on a string but the point is the type specifies these things it specifies that the what data the variable can hold and how big that data can be right it's going to because you need to know how much space and memory you're going to need to allocate for this the compiler needs to know that and also what operations are going to be performed on it so what that's for is eventually the compiler is going to have to take these these operations that you type and go and compile them into machine code instructions for whatever the hardware platform is and those machine code instructions can be different depending on the type so for instance you can easily have an ad for an integer an integer add a machine code instruction which is different than a floating point ad right integer division which is different than floating point division and so on so uh th this is why the compiler needs to know the types so it knows how to do the compilation how to convert it into machine code [Music] so we're talking about variables and we're going to talk about how you initialize them but first let's finish up the types so every variable has to have a type and you can make type declarations where you actually define an alias an alternate name for a type so sometimes this is useful uh for clarity inside a particular application for instance here uh where can you imp it could help you say say you've got you've got some kind of application and it's working on temperatures temperatures are something that's manipulating right and every temperature you want to be a floating point value 64-bit floating point value so you can define a new type or an alias for a new type type celsius float 64. in that case celsius is exactly the same as float64. now you can always declare your variables to be float64 but celsius might make sense in the context of the application right maybe application is about temperatures so maybe you want to rename it just to make it clearer for you as a programmer also like uh the next one type id num int maybe i want to maybe you know this i'm making some code that implements a database of users or something and every user has an id number so i know this type this concept id number i'd like to i know it's an integer but i want to name it i want to give it that name id number so that i know every variable that it declares an idenum it is an idenum i know something about it just based on the name of the type so once you declare a type like this type celsius float64 type idnumint you can now declare variables using that alias so i can say var temp celsius right and now temp is going to be a flow 64 because 64 is just flow 64 is alias by celsius also var pid id num pid is actually an integer but we call it an id num and it makes things more clear so initializing variable values uh every variable has to be initialized somehow before you use it one way to initialize it is in the declaration itself so you can say var x int equals 100 and that will make x an integer it'll declare it as an integer but it'll also set it equal to 100 or you can just say var x equal 100. now if you do that you're not saying you want it as an integer so it will infer the type the compiler will infer the type based on the type of the right hand side value so the number 100 is an integer so it says oh x must be an integer makes it an integer now remember sometimes this is an issue because maybe it just infers something that you don't want right i like to specify myself but maybe so for instance say i say x equals 100 but i really want it to be a floating point i mean 100 something right but i call it 100 because that's my initial temperature that i want but i want to be a floating point value this will if i don't specify it'll say well 100 could be an integer it'll infer it as an integer and then if i try to set x to 100.1 i'll have a problem now uh so i like to specify the type but you know you don't have to uh next up initializing after the declaration so you can just say var x int and then after the words you can say x equals 100 and then on a following line and that's another way now if you don't explicitly initialize a value a variable it will still get a value it'll get the zero value for its type so for instance say i say var x int the zero value for its type is zero right so x will be automatically assigned to a zero initialized to a zero if i don't say anything else if i say var x string the zero value for a string is just the empty string so x would be initialized to the empty string in that case now another way to initialize variables is using a short variable declaration now in this case you're performing the declaration and the initialization initialization together using a colon equals operator so like there i uh up on the slide x equal x colon equals 100 okay when you say that uh it this is a this is a case where x has not been declared yet right so this statement actually declares x and assigns it initializes it now the declaration what happens is when you use that colon equal the type that it that it sets it to be is whatever is on the right hand side so 100 in this case it says it looks at 100 says oh that's an int and it infers x to be an integer and then it assigns it to the value 100. so variable is uh is declared as a type of expression the type that's on the right-hand side so it does this type of shirt variable declaration it does the declaration and the assignment together in one line with this special operator you can only do this inside a function so you can't do a short variable declaration outside a function that's not legal so just know that [Music] welcome to second module we're going to start talking a little bit more detail about the go language we'll talk about data types and go the basic data types that's what this module is really about we'll go over data types that you've seen in other languages integers floats boolean strings variations on those so you can change the length of the integer length of the float things like this so we'll talk about those data types we'll talk specifically about how to declare them how to create them and what functions are available for them so what functions can you apply to integers what can functions can you apply to strings and booleans and flows and once you're done with this you'll be able to use basic data types inside your go code [Music] so in this module we're going to talk about basic data types and we're going to start with pointers which maybe is an unusual place to start the discussion of data types but that's where we're starting because people who are taking these courses generally already know something about programming so let's go straight to these pointers and talk about them a pointer is an address to some data in memory so like i was saying a very every variable is located in memory somewhere it's some data staying in memory somewhere also functions and so on they're all in memory somewhere a pointer is the address of that in memory typically a virtual address but that doesn't matter to us too much right now so uh with pointers there's a there are two operators two main operators that are that are associated with pointers the ampersand operator right there uh that returns the address of the uh the variable or the function whatever the name is referring to and the star operator which is dereferencing does the opposite of the ampersand it returns the data at the address so the ampersand operator if you put that in front of a variable the name of a variable that will return you the address of that variable the star operator goes the other way if you put that in front of a uh a pointer right to some address put that in front of an address it will return you the data at that address so uh it's important to understand this ampersand operator and the star operator are opposites of one another so i'll give you an example take a look at this uh this code little piece of code we define our variable x is an integer uh it's equal to one and then y it's an integer and it's not initialized so that would mean it would be by default initialized to zero then a var ip so ip is it's not declared to be an int it's a star end right so that means i p is actually a pointer since there's a star operator in front of the end ip is declared to be a pointer to an integer so i p is the pointer but it is not an actual integer as they pointed to an integer so then if we go on i p equals ampersand x x is actually an integer right integer whose value is one so there's a number one sitting in memory somewhere and uh x is a reference to it the name of that ampersand x is the address in memory where i can find that value one so i p is now equal to that address so whatever the address of i of that one is rather uh of x whatever that address is ip is the pointer to that address it is the address now then in the next line i say y equals star i p so remember that in this little example ip is actually a pointer and the data at that address that ip's pointing to is the value one now star ip star does dereferencing star says star returns the value the data at that address so y is now equal to the data at the address that ip is pointing to now if you remember from the line 4 ip is pointed to what x is pointing to right so i p is pointing to the value 1 that data in memory so y is if y is equal to star i p y is equal to 1. so this now sets y equal to 1. it's just a little example here just trying to show how the ampersand and the star operators work opposite to one another so these are pointers and pointers exist these points are basically if you know c uh same type of implementation now uh there's another function called new it's another way to create a variable and new returns instead of returning a variable it returns a pointer to the variable so the new function creates a variable and it returns a pointer to that variable so this is unlike if we were just declaring a variable right that also creates a variable but new explicitly returns a pointer to a variable so the variable is initialized to zero by default with new so for instance here if i say if i say pointer equals new int and then star pointer equals three right point equals new int that returns me new and returns me a pointer to uh to an integer and that ptr is equal to that pointer then i can set the value of that integer by referring to star point star ptr right because star ptr is the value that ptr is pointing to if i say star ptr equal 3 then the value 3 is placed at the address specified by ptr [Music] so we're going to talk about what the scope of a variable is roughly the scope of a variable is the places in the code where a variable can be accessed okay so variable scope defines how a variable reference is resolved in the code so if you reference a variable x how does the does the program figure out where which variable x you're talking about okay that's basically what variable scope is so in these little examples just to show you an example of scope if we look at the first block of code we've got this variable x i'm highlighting in red right and this variable x is defined outside of these two functions i've got these two functions defined function f and function g right but outside of both of them i've defined this variable x so var x equals whatever is one then i define my function f and function g now if you look inside function f and g they're very simple all they're doing is they're printing uh printing x they're both printing x that's all they're doing so inside function f and inside function g when you call these functions they've got to figure out where to find the value for x now in this case uh they they're going to find the value that i've defined outside so where i say var x equals 1 they're going to when they print out x they're going to print out 1 for x because of uh because the scoping rules allow that so basically because it's defined outside of either one of these functions both of them will have access to it and we'll define the formal rules for that in a few slides now the next block of code you get a problem because the next block of code again you've got function f and function g but this time variable x is defined inside function f but not inside function g right it's only inside f so function f will print print properly because it'll look at x and resolve it since it's defined locally right there inside its function we'll say oh x is equal to 1 it'll be happy but function g will have no reference to x it won't be able to see that and it'll throw an error when you try to run that because they won't know what x is so this is the type of problem that needs to be resolved you don't want to run into this type of problem you want to be able to know where your variables get resolved to and so that you don't have problems like this so we're going to talk about variable scoping right now so how does a compiler figure out you know where a variable reference should be resolved to you know which x are you talking about is this x or is it that x so in in go variable scoping is done using blocks now block is a sequence of declarations and statements within matching curly brackets so those curly brackets right there you have an open curly bracket close curly bracket everything in between is called a block so that's how you explicitly define blocks and you notice how these blocks can be hierarchical right you can have curly brackets and then within that you can have some other curly brackets within that you can have some more so you can have this hierarchy of blocks and these are explicit blocks when you put the curly brackets in your own code those are explicit blocks that you as a programmer included function definitions notice are defined by curly brackets right you uh we haven't gotten to functions we'll talk about it more later but every function definition you define the function give the name of the function and then you have open curly brackets close curly brackets every function you've got curly brackets so there's a hierarchy of these these curly brackets and hierarchy of these blocks now also there are implicit blocks inside this hierarchy so they're blocks that are implicitly defined without the curly brackets so just to list those blocks first there's the universe block right that's all go source code that is the biggest block the universe block there's a package block so every package even though you don't put curly brackets around every package at all the source code in a particular package that's all within one block which is inside the universe block uh then there's a file block right file block every all the source code in a single file is within the file block and remember that package can be composed of many files right so there can be one package block that has many file blocks if you've got a lot of files inside the package now then other implicit blocks include the if statement for statement and switch statements all these have curly brackets uh that that define their own blocks also the clauses inside a switch are select we'll get to these in more detail later but these are all all the ones i'm listening here are these implicit blocks that you don't have to put explicit curly brackets for uh well so you can so for instance an if statement you can use if curly brackets too but like the universe block the package block file block these are all implicit blocks and there's a hierarchy of these so that's my point that there's these hierarchy of these blocks and each block can have its own environment of variables associated with it okay so lexical scoping this defines how how variable references are resolved so go is a lexically scoped language using blocks so when we talk about lexical scoping we've got to talk about this relationship of uh being defined one block being defined inside another block okay so i'm using this terminology here i'm saying bi is greater than equal to bj if bj a b is a block okay if bj is defined inside bi then b ah then b i is greater than or equal to bj okay so i would say that bj if it's defined inside bi bj would be you refer to it as an inner scope where the outer scope that includes bj is bi okay so uh just as an example of this it's a transitive relationship but just as an example of this look at the code we got um we've seen this code before got variable x we initialize that to one then you got function f and function g now if we look at this the blocks inside here first you've got this is all in one file right so all of this is inside the file block and i'm calling that b1 so b1 is my file block and everything is inside the file block but in addition to the file block i'm defining two functions f and g and i'm each one of these function blocks functions gets its own function block so b2 is a function block for f for f and b3 is a function block for g so if i were to look at how these these blocks are related b2 and b3 are both defined inside b1 so i say b1 is greater than b2 and b1 is greater than b3 by my definition because b2 and b3 are defined inside b1 but notice that there's no relationship between b2 and b3 because they're not defined within each other okay so uh we need to know this because the scoping the scoping rules when you're resolving a variable you go to the greater including scope so for instance if inside b1 the function f right inside that block you're referring to variable x then it's going to look for that variable x inside b2 itself inside its local block but then it looks for the next bigger block that is defined inside so it starts in b2 looks for the block if it looks for variable x if it doesn't see it there which it's not defined there in this case then it says okay what is the next bigger block that i'm defined inside it would get b1 and would look inside b1 and say ah there is a definition of x here and that's the definition of x that it would use same goes for b3 right and if you look at the function g it it uses variable x it acts as variable x and first it looks inside its local block b3 it doesn't see it so it looks inside the next bigger block that is defined inside b1 and it sees it there so that's why this works this way this code will work the x will be resolved properly so that x equals 1 that variable that we defined inside b1 so when you're talking about scope of variables a variable is accessible from a block bj if the variable is declared in some block bi and block bi is greater than or equal to bj so it's either the the variables you declared right there in bj or it's declared in some outer block that's greater than bj so that's why in the first block of code first block the first uh code sequence you can see where x is defined inside the file block both of those functions which are also inside the same file block they can both properly access the x variable because their blocks their function blocks are within the file block but in the next block of code next sequence of code the x is defined inside the function block of f but it's not inside the function block of g so when g tries to reference x x the variable x it doesn't see it in its local block it also doesn't see it in its file block right because now the definition is inside the function block for uh for function f so that's why this block this fails the f x doesn't get resolved back to anything and there's an error [Music] so we've been talking about variables and how they're referenced uh variables they're all referring to uh some data that's somewhere in memory so the variables eventually have to be deallocated in memory so allocated and deallocated so what i mean is once you declare a variable and your code is running your space needs to be allocated somewhere in memory for that variable if it's an integer there has to be some allocated space dedicated to holding that integer and at some point that space has to be deallocated when you're done using it right so when you're done using your variable x you want to be able to say oh that space is now free and it can be used for other purposes so that's deallocation when you make memory space available for other purposes you have to do this in a timely fashion so otherwise you eventually will run out of memory in your machine so for example if you look at this piece of code it declares a variable x var x equals one so the process when it runs it has to allocate a memory location just for x to hold it now say you call in your program f you call this function f a hundred times right then it's gonna allocate a hundred different spaces for this variable x right because the x goes away after the function completes the x goes away it's going to allocate it again it should go away you want it to go away but every time if you don't de-allocate it you'll execute every time you execute this function f you'll get a new variable x allocated and so you'll have all these spaces allocated in memory and really you don't need them anymore right i mean once a particular function call ends you no longer need the space that for x for the exit it was using so at some point you have to deallocate this memory you have to say look this memory is now free because otherwise you would eventually use up all your space and you might think well you know how am i going to use it my space i've got you know x number of gig on in my memory system you can eat that up very quickly right and believe me this is called a memory leak this is a thing that happens uh in c a lot uh you can eat up all your space very quickly so you have to de-allocate this space in a timely fashion now in order to talk about how space is deallocated we got to talk a little bit about where the space is stored in memory so memory is a big thing but there are two big hunks of memory that are relevant to us right now the stack and the heap now the stack is an area of memory that is dedicated to function calls primarily dedicated to function calls so one of the things stored in the stack are the local variables for a function so every time you call a function there can be variables that you define in that function and generally they go into the stack they are allocated in the stack area of the memory and they're deallocated if they're allocated in the stack they are deallocated automatically when the function completes now this is this is different a little bit different for go this is traditional what i'm talking about now is how it works in regular languages go changes this a little bit okay but normally the stack is the area of these local variables where when the function is done the variables are deallocated automatically now the heap on the other hand is a persistent region of memory where when you allocate something on the heap it doesn't go away just because the function that allocated it is complete that heap memory it you have to explicitly de-allocate it somehow in another language so if you were in say c you would have to explicitly de-allocate this now go does a tweak on this but it is still important to understand that memory variables can be in the stack which will for the most part automatically go away when the variable will be deallocated automatically when the function is done or in the heap where it's persistent now if you're in another language like c then you have to manually de-allocate things on the heap on the the stuff that's on the stack you don't have to manually de-allocate it it'll go away when the function completes but the stuff's on the heap you have to manually explicitly de-allocate it so like say you were working in c if you want to allocate memory on the heap you would call a function called malloc and say i say x equals malloc 32 it'll allocate 32 bytes of memory and x will be appointed to that and then later when that's how you allocate it later when i want to free it i can say free x and it will free that space deallocating it so error prone but fast so what i mean by that is it's error-prone because it's easy to make a mistake in your allocation and de-allocation de-allocating it the wrong time or forgetting to de-allocate it stuff like this it can cause you headaches and uh it's error so it's error-prone in that sense but it's fast right the implementation is very fast you don't have to see what happens with de-allocation like in an interpreted language is that the interpreter does it okay and that can take time so but in a compile language like a c uh you would have to do that manually [Music] so we've been talking about deallocation de-allocating memory and it can be hard to determine when it is appropriate to deallocate a variable reason is because uh you can only de-allocate a variable when you know the variable is no longer in use right you don't want to de-allocate a variable and then later need that variable that you deallocated because then it's basically gone right so it's hard sometimes to figure that out figure out when it's uh when it's not in user or when it is in use and so on uh so here's an example uh a go example which is this is legal and go but because this is a pain this is not legal in certain other languages but in go this is a legal thing if you look at the first function foo inside there we declare this variable x so it's a local variable to this function foo and what's returned though is the address of x ampersand x right a pointer to x now then in the main function down below the main function calls foo and then the main function uh what happens is since it calls foo and it uses it gets a the return value of foo actually gets assigned to a variable in the main function so the trick here the confusion here is that this this program foo normally if you declare a local variable x when the function ends that variable x should be deallocated right you're done with it because the function is done with it but in this case it's not the case because it's returning a pointer to x so now the main since the main now has that pointed to x since that's getting returned to the main the main might still use that pointer tags so that you you can't just say oh well foo is now done i can get rid of its local variable x because maybe main is going to use that local variable because now main has a pointer to it okay so this is actually a legal thing to do in in go so this is just one example of how pointers especially make make it difficult to uh to tell when de-allocation is legal and when it's not so deallocation is a complicated thing so what people do one way of dealing with that is to have garbage collection so garbage collection is basically automatic or an automatic tool that deals with uh deallocation so this is part of interpreted languages and it's done by the interpreter so if it's say java you'd the java virtual machine or in python it's a python interpreter something like that and it keeps track of these pointers and it determines when a variable is not in use anymore and when it is and once it determines that a variable is definitely not in use there are no more pointers no more references to that variable then the garbage collector deallocates it only when it all references are gone so this is uh this is nice garbage collection is a nice thing it's easy for the programmer right programmer doesn't have to worry about exactly when the allocation when to do it when not to do it believe me deallocating memory is a big headache in other languages say c or something like that but it requires an interpreter so generally compiled languages like c c plus plus they can't do it but go is different okay go is different and better in this sense so go is a compiled language which has garbage collection built into it so that is a unique feature go which is really nice so as a result the go go compiler can figure out uh it can figure out when like it can follow these pointers to some extent and figure out when this these points are still in use and it basically keeps track we're not going to go into garbage collection because that is a complicated thing there are many ways of doing it but generally you have to keep track of the pointers to a particular object and once all the pointers are gone then you know that the object can be deallocated and so uh garbage collection and go allows actually two things one thing is it'll actually allocate stuff on the hat heap and the stack itself so you as a programmer don't have to determine i want to put this on the heap i want to put this on the stack the go compiler it'll put code in there it'll at compile time it'll figure out this needs to go heap this needs to go to the stack and it'll garbage collect appropriately so if it's on the heap it will garbage collected appropriately you'll see when all the pointers are gone and it'll determine um you know when it can be garbage collected when it can be deallocated and this is a really helpful thing now there is a downside because the garbage collection the active garbage collection does take some some time right so there's a performance hit but it's a pretty efficient implementation and garbage collection is so darn useful it's probably worth it to put it in go so that's a trade-off that go makes it slows things down a little bit but it is to great advantage because it makes programming a lot easier and you don't have to go as far as using a full-on interpreter like you would in an interpreted language [Music] so we're going to continue talking about the basic data types but a couple of things i want to hit on are comments and print statements uh so it's interesting when talking when teaching a class about programming language it's there's some things that you you know you have to teach it linearly right one thing at a time but some things are basic concepts that i have to use very early on so i'm going out of sequence a little bit but these are comments and printing print statements i use all the time i've even used used them already so i need to define those then i'll keep going with uh with what with the variables okay so uh comments comments this is pretty straightforward uh these are basically c like comments they look like the same as in c uh single line comments are just a double slash so slash slash everything to the right of the slash slash on the line that's a comment which means it's completely ignored by the compiler it's only text for the programmer to to look at to understand to help with the understandability of the code which is a useful thing okay comments are excellent things when used appropriately but uh you can see here you can just say slash slash this is a comment and then everything to the right of it which is everything on that line is going to be a comment stuff i've highlighted in red there right then on the next line i declare a variable var x int and i say slash another comment in that case uh the slash slash everything to the right of the slash on that line is comment but the stuff on the left is still valid code so the stuff on the left gets compiled the stuff on the right is ignored by the compiler now in addition to these single line comments you've got block comments and those are marked off with the slash star and the star slash so slash star begins that star slash ends it everything between the slash star and the star slash is comment so in this case it's just two lines but i could have any number of lines of code if i wanted to have a lines of text whatever i could have any number lines of text describing a function or something like that uh mark that put that as a block before the function if i wanted to so those are comments now an additional thing that i've already been using are print statements just because they're so useful printing it's done using the the format package fmt package so you have to import the format package import format at the top of your program then uh printf is sort of the first standard print com print function you use a format dot print it it prints a string so you pass the string as an argument to printf so format dot printf uh quotes high a string is delimited by these double quotes and we'll talk more about strings but the simple way is just double quotes uh or i can say x equals call x colon equals joe and then format printf hi plus x right so plus is a concatenation operator that concatenates the high and the next string x right which is the word joe so that would print out hi joe with space in between now we also we're going to use format strings format strings are strings that are used for formatting the output to make it look nice and basically all format strings are they're strings double quotes but inside the string you use what are called conversion characters so in this language there and go there you use a percent percent and then some other character so for instance if you look at the example format printf says hi and then percent s percent s is a a conversion character for a string so what's going to happen is wherever you see the conversion character that character will be substituted by uh by some variable in this case since it's percent s that means a string so it expects a string so if we look at the arguments to printf the first argument is the is you know high is the string high percent s that's a format string the next argument is the x that x is going to be some string that is going to be substituted in for the percent s so if x is the word joe then when i do this print statement it's going to say hi joe right because joe will be substituted in for the percent s so this is a commonly used these format strings are commonly used to to make the format look nice when you're printing so besides the comments and the uh the printing let's start talking a little bit about integers and the nature of integers so first there's a generic in declaration we've already declared some integers uh var x and right now there are different varieties of integers generally uh for the most part we're not going to care we just say var x int and leave it to the compiler to figure out what type of integer what length of integer to use most of the time but you can have different lengths of integers to and uh so for instance here you got in 8 and 16 and 32 and 64. and that those uh those numbers are the number of bits that are used to represent the integer in memory so 8-bit integers 16-bit 32-bit 64-bit then you went are unsigned integers so and also 8-bit 16-bit 32-64. the difference between ants and u-ends uints are unsigned so that means that they can get larger meaning there's a normally in uh we're using two's complement arithmetic inside our machine so the most significant bit is the sign bit and an unsigned integer that most significant bit is not used for the sign it's used for magnitude representation so the magnitude the absolute value of the unsigned integer can get bigger just because you have that extra bit that would have been used for a sine and a regular integer you can use it for magnitude uh so the difference between these different lengths of integers is uh just how big do we need the integer to be so an 8-bit integer let's say that can only represent uh you know x's say it's an 8-bit unsigned let's say inside for a second that could represent 0 to 255 because that's the biggest number you can represent with 8 bits but a 16-bit integer can go from 0 like an unsigned energy you can go from 0 to 64k which is about 65 000 and thereabouts so it's much bigger so the number the more bits you use the the bigger the number representation can be the safest the most common thing to do is just to declare it as an int and leave it to the compiler to figure out but if you happen to know the magnitude of the numbers that you want you can control that by specifying what size energy you want uh now integers also have a set of operators binary operators i'm showing right here they're also unary operators but these are the binary ones these you've seen these in every language you know plus minus times all the arithmetic shift uh modulo comparison operator so equal equal is a comparison equality comparison exclamation equal that's not equal greater than less than and so forth they're boolean operators so and or and then bitwise operators where it does uh boolean operations per bit inside the inside whatever the integer is so you can see those two but these are common to basically to all not all but all standard languages have the same set of operators that you can operate on interest with [Music] so uh we talked about integers now let's talk about type conversions a little bit before we go on to the next basic types uh there are cases where you need to convert a number or a value from one type to another type and for that you use the type conversion now these conversions are not always possible okay you can't necessarily do those conversions but when they exist here's how you when they can do when you can do them here's how you do them uh let's say okay so let's say for instance you got some some integers of different lengths so i've got variable x it's a 32-bit integer and uh variable y it's a 16-bit integer and i want to say x equals y i want to assign one to the other or i want to do some operations with them together that uh as shown would actually fail reason why they fail is because these two integers they're actually two different types of integers they're the so the compiler sees them as two different types n32 is a different type than n16 so it'll throw an error when you try to set one to the other because when you assign like that the two things the thing on the left-hand side and the right-hand side they have to be the same type and it sees them even though they're both integers the fact they're different length means they're different types and it throws an error so in order to do this you've got to convert one to the other so for instance you might say let me take that y which is in 16 and convert it to an n32 and then assign x to that and then that would work so the way you do type conversions like that is you use the uh this t operation where t is the type the name of the type so if i want to convert y into 16 into an n32 i just use this enter this built-in function in 32 right and that will take whatever its argument is and try to convert it into it in 32. and so x equals n32y that's what it would do would take y which is n16 convert it to n32 now this is a conversion that is possible all it has to do is its sign extends the um the y integer so the y value you don't want to change y's value is equal to two right so y is a 16-bit version of two and they want to make it into a 32-bit version so what it's going to do is take the sign bit and just extend it so if the sign bits is 0 meaning it's a positive value it just puts 16 0 bits and the high bits gives you a 32-bit number which is equivalent also 32 represent 32-bit representation of 2 says that's equal to that so this is the type of conversion that's possible uh so it's easy to do so you just use this in 32 function to do it note that there are other type conversions that you can't do so easily and it will fail on those but but some of them are possible like this one so another type besides integers are floating points so floating points uh they're basically real numbers right now depending on how many bits along the floating point is let's say you got float 32 that's going to give you approximately six decimal bit digits of precision okay float 64 is going to give you approximately 15 decimal digits of precision so you uh you figure out how many bits you want to use how big you want to be based on how much precision you need and often it tends to be you want to go longer than shorter right because precision errors are a common problem in floating point arithmetic so you want to use more precision the more positions probably the better of course there's a space issue right use more memory uh if you make them longer and also performance changes right but still um you know you don't want it precision errors are are an issue sometimes so uh you can express floating point numbers with decimals or in scientific notation so we can see two bar x is float 64. uh one 123.45 right that's a decimal it'll make it a floating point representation also you can represent the same thing scientifically with this e as the uh the exponent right for the uh for the for the 10. so this is base 10 so e2 means 10 to the 2. uh also you can represent complex numbers if you want to they have complex complex numbers so if you remember complex numbers from high school wherever you learned it you get the real part in the imaginary part uh so this is how you create a complex number you use this complex function it creates a you give it two arguments the first number is the real the second number is the imaginary so 2 plus 3i would be that complex number if you're using complex all right so uh first we're going to talk about strings in order to talk about strings we need to talk about ascii code and unicode so strings are going to be sequences of bytes uh we'll see that in the next slide but each individual element each bite in a string strings are made to represent uh different characters that you see okay so often strings are made for printing they don't have to be for printing but they're often made to represent printed things so for instance hello world the string hello world right that's something that's meant to be printed and seen by a user so uh now the each one of these characters that you want to store in a string each character has to be coded according to a standardized code ascii was basically the first accepted one american standard code for information exchange and it's just a character coding so each character that you uh that you want to represent is stored with a is represented with a uh an 8-bit code so for instance a capital a right a capital a in ascii is the number 41 in hexadecimal okay i i just know that on top of my head it's a common code but it's 41 in hexadecimal so that's an 8-bit code so ascii is an 8-bit long code which means it can maximum represent 256 possible characters really does 128 because one of the bits is used for something else so that's not a lot of characters so an 8-bit code is sufficient for english because there aren't that many letters in the alphabet but uh once you start incorporating other characters that that you need to include so for instance chinese is a good example because there are a lot of characters in chinese right you can't use an 8-bit code and hope to represent chinese so once you start trying to look at all these different character sets in different languages and different characters that maybe even aren't part of languages but things that you want to do that you want to represent anyway you want to show and have appear on the screen you need a lot more than eight bits so that's what unicode is for unicode is a character code that is a 32-bit long code and so you can represent 2 to the 32 which is a lot bigger 2 gig 2 gig i think so it's a lot bigger so that's a lot of characters now utf-8 is a sort of a say a subset of unicode it's a variable length code so it can be eight bits but it can go up to 32 bits and the first eight the first set of codes in utf-8 match ascii right so all the ascii code values are the same as the you they're utf-8 values so for instance a capital a it's it's in hexadecimal it's a 41 in ascii it's also a 41 in utf-8 right now utf-8 also includes a lot of other codes like for instance chinese characters right and those aren't in the first in the uh the first 128 right they're outside of that they require more bytes uh you can't just use a third eight-bit code to represent those so maybe those are 16 bits or 32 bits so utf-8 is a variable length code but it can carry it it represents a lot more characters than you can represent with ascii now the default in and go is utf-8 and in utf-8 or unicode code point is a term for a unicode character okay so there can be up to two to the 32 code points right and in go they call a code point a roon so roon is just a term for a code point so in the character uh the capital a character it has a rune which is represented with ox41 right in hexadecimal it's a 41. that you call that it's roon okay now to strings now strings are arbitrary sequences of bytes uh represented in utf-8 so each byte is a rune uh represented as a utf-8 code point so these strings they're read only you can't modify a string you can make a new string that is a modified version of it is this existing string but you can't modify an existing string often meant to be printed or displayed to a user a string literal is just a string that's notated with double quotes so for instance if i say x colon equals hi there that's a string literal right and that's a sequence of bytes each one of those bytes each one of those characters h i space t h e r e each one of those is going to be represented as a rune a utf-8 uh code point uh and they're put together in an array of an array of those will cover arrays soon but an array of those is going to be a string [Music] so we've already talked about strings strings are a common construct you see them in every programming language and strings are made of uh made of unicode unicode runes they're string basically arrays of runes so there's a package called the unicode package which provides a set of functions that actually evaluate the properties of the different runes inside the strings and it's useful if you're doing uh if you've ever done parsing you know you want to parse some string out right out of a file or out of a uh maybe something somebody typed it in directly as user input and you want to evaluate that string when you're doing parsing you need functions like these so they're a long set of functions that the unicode package provides to evaluate the runes all right here some of them here are is digit tells you if the rune is a digit a numerical digit is space is its base character is a letter the letter is lower or lowercase is punctuation is punkt so you and these are all binary uh boolean right so they return true or false depending on if the rune is what it what it's saying to be if it's a digit or space or so on uh there are also a set of other functions that perform convergence so some of these conversions are possible for instance two upper and two lower you can take a lowercase roon turn into an upper case room right and vice versa so they provide functions for that so they take a rune like two upper it takes a rune which is a lower case and returns a rune which is an uppercase and so on so unicode package is useful for that but there are other packages that are also involved in manipulating strings there's the strings package so the strings package the functions that it provides are things to uh directly not look at the individual rooms generally but i'll look at the whole string so there are a set of search functions that are provided inside the strings package these are common functions that you see in lots of different languages also so for instance first one would be compare compare a b you give it two strings and it compares to see if they're equal and actually this compare function it returns a negative one it returns zero if they're equal returns a negative one if the if a is less than b meaning earlier than it in uh in alpha numeric order and a it returns a positive one if a is greater than b so if a is later than b in alphanumeric order so this compare contains so you give s a string and then a substring if that substring is contained inside s it returns true otherwise false has prefix so you give it a string s and a prefix if that and it returns true if that prefix is the if s starts with the prefix and index s and you give it a sub string what that does is a search it searches for the sub for the substring inside s and it returns you the index of where the first instance instance of that substring can be found inside s if it can be found so this is the strings package now the strings package also provides a set of functions that manipulate strings now when i say manipulate you can't change change a string a string is immutable but uh there are a lot of functions that take an existing string and return a new string that is some modified in some useful way so first one would be replace uh with replace you basically take a string and it allows you to replace uh instances whenever it finds an occurrence uh of of old it replaces it by an occurrence of new so these are all strings so it's a big string s there's a substring old and another substring new replaces instances of old with instances of new and returned to a new string so s the original string is not actually changed it returns you a new string with the replacements performed two lower two upper so this will take the whole string and change it to lowercase or uppercase uh return i keep saying change it does not change the string it returns a new string that is modified also trim space is useful uh that gets a little rid of leading and trailing white space from a string so you get this a lot when you're reading from a file let's say and uh you know the maybe the the tokens on the file are separated by spaces so if you just read directly from the file you'll also read these spaces in but you don't need the spaces you just need the token so you may call trim space to get rid of the spaces another package uh that has a lot of useful functions for strings there's a string convert package so generally this provides a set of functions for converting uh converting strings from and from different basic data types to and from different basic data types so some of the big ones a to y as ascii to integer is what it stands for and it converts a string to an integer if that string represents an integer so uh let's say you're reading uh from a file you're reading a string from a file and the string is a number one two three 123. now when you read that and you read that as a string you can't do math on a string right you can't take that 123 and add one to it because it's a string type it's not an int type so you need to read that string in and then convert it to an int and then you can do math on it so you would use a to you to do a thing like that and idaway does the reverse uh it takes the uh converts an ant into a string an equivalent string uh then format float basically does a similar thing for floats so it converts a floating point number into a string representation of that floating point number and then parse parts float does the opposite converts a string to a floating point number so a string uh so if you have the string 123.45 and as a string it'll convert that to a floating point number that you can actually do math on [Music] so let's talk a little bit about a constant so a constant is pretty obvious what a constant is it's an expression whose value is known to compile time right so you know it and it never changes uh so you can just basically declare a variable to be a certain value and it holds that value for all the time as long as the program is running the type is inferred from the right hand side of the of the assignment so for instance here we've got let's say const x equals 1.3 so that's going to set x to the value 1.3 and you can the compiler looks at 1.3 sees that that's a floating point and so x becomes a floating point so it infers from the right-hand side of the of the assignment what the the type of the variable needs to be and it is held constant can't be changed uh you can assign many at once so constant we have we know y equals four z equals high right you can give a long list if you want to so that's what a constant is now iota is a is a function used to generate constants it's sort of interesting so it generates a set of related but distinct constants so when do you use this you use this when you have to represent some property or some some property that has several different distinct possible values so this is also known as one hot so if you know there's a basically if you have a variable and you know it's going to be one hot coded right this variable can have one of five values let's say and so you want each one of these five values to have to be a distinct constant right now in a situation like this and just examples of such things days of the week right you got seven days of the week and you want each day of the week if you want to define a constant for each day of the week monday tuesday wednesday you want them all to be constants which are different but um which are different you don't particularly care what the value of the content is as long as monday is different from tuesday which is different from wednesday months of the year is the same thing right so key thing about these constants is when you use iota to generate these constants the constants need to be different but the actual value of the constants is not important so if i have monday tuesday wednesday as my constants i don't care if monday is 500 or 5000 or 2 or something as long as monday is not the same as tuesday which is not the same as wednesday right so that's the case where you can use iot if that's the case you need to represent some set of constants be all different values you don't care exactly what the value is but as long as they are distinct constants then you can use iota and this is essentially just like an enumerated type in other languages like in c or something like that it's the same idea so they give you a nice little shorthand for defining these set of constants so here's a little example of how you might define something using iota say i wanted to find some grades so i make a type called grades i'm making an ends i want to represent my my grades as integers and i want to have these five grades a b c d and f and i don't i know that i want a b c d and f to be all different grades right so they should be represented by different integers but i don't particularly care what integers they're represented by i just want a to be something different than b and c and d and f so i declare the constants a b c d and f and the first one i say a give the type grades right which is actually an ant it's an alias for int a grades equals iota i say that on the first constant definition then for b c d and f i don't have to repeat that right you can see i just say b c d and f i don't give the type i don't say iota none of that so just do it on the top and what will happen is automatically iota will assign a value to the first constant and then it'll assign a different one to the next one a different one to the next and so on and actually what it does what the implementation does is that it assigns it starts at one so a would be one b would be two c would be three but you should not depend on that right that's not um so you don't know the idea behind using iot is that you don't care what the actual values of the constants are you just want the constant values to be different from one another so it happens that the current implementation starts off at one in increments but you can't guarantee that in the future maybe that's going to be changed right just all you know about iota is that they're going to be different [Music] so control flow describes the uh the order in which statements are executed inside a inside a program now basic control flow the most basic control flow is just executing one statement at a time one after the other right procedural control flow just top down all right now the control flow changes for a lot of reasons but the first reason why control changes is because the programmer inserts control flow structures into their code which changes the sequence in which uh statements are executed so the main control flow structure the first one as an if statement uh basically within a statement you can conditionally execute certain sequences of code so if this condition is true then you execute the sequence of code if not then you don't right and this what we're showing here is the sort of the most straightforward if statement uh without an else clause you can also have an else clause but uh let's start with the basic one first so uh the structure is just if condition you write some condition in there x greater than five something like that uh and this condition has to evaluate to a boolean right if that condition's true then whatever's inside the curly brackets uh labeled consequent there that's executed and you can have any number of statements inside there and that'll be executed if the condition evaluates to true so uh so this changes conflict control flow because instead of just definitely executing the next statement one after the other it checks this condition if the condition's false and that consequent those statements in the consequent are not executed at all and so uh we can see at the bottom we got you know if x greater than five then it prints uh it just it performs a print statement right and if it's not then it just skips that entirely now this if statement this is a very vanilla if statement uh you can also have an else clause after that right so if the condition's true it executes what's inside the curly brackets then you can have it next clause the else clause it would execute whatever is inside the next set of curly brackets the next the next block for the else right uh we didn't include one here but uh but this is a straightforward extension and you see this in every in every major language so for loops they're another form of control flow control flow statement uh again so for loops what they do uh they basically uh they they're loops so the control flow rather than just going top down when you hit the bottom of the loop you come back to the top of the loop and you do it again and again until a certain condition is met or not met so uh that's how they alter control flow it's just uh and this these are extremely common in programming using loops so they just iterate over a block of code uh as long as the condition is true now they the there are several forms of four statements we're looking at one right here that probably the main the most common form you see it uh similarly in c and things like this if you look at the keyword four right after that there are three three uh statements really there's the initialization statement init there's a condition and there's the update and separated by semicolons so the init is executed once at the beginning of the loop so the first time you hit the four the for loop it executes the init just to initialize things right at the top then the next block that condition that is checked on each iteration so at the beginning of each iteration that condition is checked if it has to result it has to be an expression that results to a boolean if that condition is true then it executes all the statements inside the loop otherwise it doesn't otherwise it's done with the loop and it continues past the loop so that condition is the termination condition it determines when you stop executing this loop because as soon as that condition is not true you skip the loop and you're done now the update that third block there the update is what is executed at the end of each iteration and it's used to update some act some element of the state so very common way in which you use this is you'll have you'll have some index variable for i i equals zero maybe start off with i equals zero and you want to do this or iterate through this ten times so the condition might say i less than ten and then the update would be i plus plus or you know i equals i plus one right and then every time every pass through it updates that that i value that element of the state so and one thing about these for loops is unless you want an infinite for loop which which you typically do not want you got to make sure that that condition is at some point false right because if the condition is always true then you never leave the loop so the way one of the ways the most common way to make sure that condition is always false is to make sure that update changes the state in such a way that eventually the updates cause the condition to be false so for instance if i say i is equal to zero i start off at u equal to zero and my update is i equals i plus one then eventually i will be greater than ten excuse me it will be greater than ten so uh so the update guarantees that the condition is eventually false and that you eventually drop out of the loop so here are um some forms of for loops these are basically three most common forms of for loop top one is what we've already seen right you've got the initialization you've got the condition and you got the update uh the next one uh the next one is if you look at the four keyword there's only the condition check after it right no initialization no update you don't have to have those now uh instead what we did here to make it equivalent to this to the for loop before we had to put the initialization before the for loop that's another way of doing it and the update is now built into the for loop so if you look there's an i plus plus inside the loop right uh so it's actually inside the four's block instead of as you have in the first form where you actually um put it in there right after the keyword but this is another way you can define a four which is really just like a while loop inside another language and then the last last form is just an infinite loop uh it just it has nothing after the for loop it just does an infinite loop which is not typically what we're going to be doing you do that maybe an embedded system but it's not common to do in a regular program you usually don't want an infinite loop all right so another type of control flow is a switch switch is paired with case right so a switch is a multi-way if statement so uh you often get case situations where you want to say if this is true you do this if this is true you do that if this is true you do that sort of you do one of a set of cases sort of an else if else if there's another way to write this type of thing so switch is like there's a set of cases and only one of them is going to be executed uh whichever one matches so the switch may contain typically contains a tag which is a variable to be checked right so maybe i say switch x so that's the variable i'm going to check then each case is associated with some constant value that x is compared to that the tag is compared to so takes compared to the constant defined right after the case keyword and then whichever case whichever case is constant matches the value of x that's the case that's executed and none of the rest are so in this example you can see we've got switch x inside you've got two cases case one case two so if x is a one it'll execute case one if x is a 2 it will execute case 2 and then the bottom one is default default is executed if none of the cases are hit so you don't it's an optional thing you don't have to have a default but you can have a default so if it falls through it'll end up executing something so this is typical form for a case and one thing to note just uh if you're used to c as in comparison to c the it automatically the case automatically breaks at the end of the case so in c if you were to execute case one say x was equal to one you hit case one you execute case one it would also fall through and execute execute case two right that's what c would do unless you put a break statement in there at the end of case one right after the the format dot printf you put a break statement then it would skip the other case in the default in switch uh in switching golang you don't have to do that it just automatically breaks which is a good good thing [Music] [Music] to continue with the the control flow we were looking at a switch let's talk about a tagless switch this is a variant on the regular switch so normal switches they have a tag right switch x let's say and that's the tag that x and that's a variable that's going to be compared to constants that are that are right after the cases right so case 1 case 2 case 3 x is compared to those constants 1 2 and 3. so sometimes that's not what you want sometimes you can have a switch without a tag and when you do that then what happens is the case that actually gets executed is the first case whose expression is true so what i mean by this is when you don't have a tag in the switch then each case is going to have to have instead of having a constant after it will have some expression that resolves to a rule to a boolean true or false and if that boolean is true then that's the case that's executed and it it'll execute the first case who's whose condition is actually true so uh here's an example of that this case we have a switch there's no variable no tag right hey we just have these cases two cases plus a default so case x greater than one uh case x less than negative one and then default so in this in this situation uh since there's no tag it just looks to the right of the the case case keyword looks at the condition x greater than one evaluates that if it's true then that's the case that gets executed and we're done to switch if it's false it goes and checks the next case to see if his condition is true and so on until you're done with all your cases and then uh if none of them happen then the default is executed if you've included a default so that's a tagless switch and you can use that as well instead of ill if else if else if you would use a switch like this tag a switch break and continue are also control flow instructions uh they sometimes are considered bad form but they definitely exist and they're used so break a break and continue for loops so a break exits the containing loop so say you're inside a loop and that loop uh so in this case we got a for loop and you know i equals 0 i less than 10 and there's an i plus plus inside the loop so this is supposed to happen uh whatever this is is supposed to iterate through 10 times conceivably but notice inside the loop it says if x equal equal 5 then break so when if it hits that break and it will in this case when it hits that break it will uh exit the loop so this thing will only execute for i equals 0 1 2 3 4 and 5 it'll go into the loop and it'll hit the break on the fifth pass through the loop so it won't finish the loop so break just jumps out of whatever the containing loop is and quits the loop now continue on the other hand it's also used in loops it doesn't quit you out of the loop it just skips the current iteration of the loop so uh if we look at the continue example same code except instead of a break it calls it continue if i equal equal five then it calls continue so in this case if without that if statement and that continue it would execute this loop 10 times right because i starts at zero it goes up to the condition is i less than uh less than 10. so it would execute 10 times but for this loop it says if i equal equal 5 continues so that one iteration where i is equal to five it will continue uh through that it'll continue and just jump right past that iteration of the loop so it won't uh so it'll still the code will still the loop will execute but uh it won't execute as many times it'll skip one iteration of the loop so a scan is a scan is a function to read a user's input this isn't a control flow function but we need to hit this because reading user input is something you're going to use in the code examples that you write sort of a common thing to do you want to read input that a user types into the keyboard so this is in the format package what scan does is it takes a pointer as an argument so what you do is you make a pointer to some to some va to some value that you expect a user to type in so if you are going to type in an integer you would make an integer and you would pass a pointer to that integer to the scan function you call scan and when you execute the scan function it blocks the the program waits until a user types in something and hits enter and when they hit enter the scan function will take whatever they typed in and we'll put it it will place it wherever the pointer is pointing okay so it will take what they typed in and put it into say an integer if you pass the pointer to an integer it will take it turn to an integer point and then put it into that integer so and what it returns is the number of scanned items it returns actually two things the number of scanned items the number of tokens that a person typed in so space separated tokens that's returned also an error the second thing's returned is an error if there's an error it'll return something other than nil there's no error it'll just return nil for that error but if there's an error it'll return an error code and we would we could investigate that so we can look at this example code let's say we make a variable apple num and uh it's an integer then we print out a number of apples question you know expecting the user to type in how many apples so we expect them to type in some integer five let's say right so the next line it executes the scan function and the code will actually stop the the code will stop running there and wait until the user types in something and hits enter so say the user types in a five hits enter now notice that the argument to scan the argument passed is ampersand apple number which means the address of the appledum variable so when they type when the user types in five scanf and hits enter that scan function takes that number five puts it into the apple variable so on the next line when i say uh printf apple number it'll print five or whatever they whatever integer they typed in [Music] welcome to module 3. now we're talking about composite data types so composite data types are data types that aggregate other data types together so they bring together lots of different data types specifically we're going to be talking about arrays slices maps and structs copies composite data types are essential for complicated code for real code because simple data types basic data types uh aren't enough to describe the complex concepts that you're going to need to refer to in big pieces of code so you need to aggregate them maybe you have strings here integers there you merge them all into one thing that describes whatever the concepts are that you're referring to in your particular application uh and once you're done with this you'll be able to use more complicated composite data types inside your go code [Music] so now we're moving on to composite data types comps to date types are beyond the basic data types they're data types that put together that aggregate uh other data types so uh so unlike a string a string is just a string actually even a string you can think of actually a string is a sort of a special case because you could think of it as aggregating these different bytes uh so a string is somewhat of actually now that i think about a string sort of is a composite data type but we're going to talk more generally about arrays right now so an array in general is just where you take a bunch of uh a fixed length sequence series of elements of a chosen type so you can make an array of bytes you can make an array of integers an array of floats and so on uh but it's fixed length then it's a key thing about arrays they are fixed length it is known to compile time how big they're going to be so the compiler can tell how much space and memory it needs to allocate for these and just in general let me say that these comp composite data types are important that is in any kind of com complicated program you're going to need to use composite data types it's not enough to use the fundamental data types yeah you need to bring together different types of different data types and group them and aggregate them into some kind of a composite data type so um so you have different array elements right each one is some chosen type maybe it's an integer array you've got a set of each array element would be an integer elements of each of the array each element is indexed by using subscript notation so square brackets you put the index right in the middle of square brackets so we have we're going to have an example here but this is a similar notation what you see in lots of different languages indices start at zero because we're computer science we start counting to zero not one elements are initialized to a zero value and actually this is not always the case in other languages uh say in you make an array that array is not initialized at all right unless you actually write code to initialize it when you create it it's not initialized but in golling the the array is initialized to zero value and when i say zero value i mean the zero value of the type that the array is composed of so if it's integers the zero value is just zero if it's strings the zero value is empty string right so uh in this example we're showing how you can declare an array so you say c at the top var x and then in brackets five int and the fact that it has a brackets five tells you this is supposed to be an array of five integers so uh that's how you declare an array and that would be initialized to zeros by default then the next line i refer to a particular element uh x zero x bracket zero right so i'm looking at the zeroth element and i'm setting that equal to two so now i've changed that online equal to two and then if i the next line i'm doing a print f so do print f x of bracket one and since bracket one i didn't actually explicitly initialize that it would have been initialized to zero so that will print to zero so that's an array and you've seen that in other languages most likely an array literal is a a predefined uh set of values that go into that are that make up an array so you use this to initialize arrays if you want to so for instance here we say var x bracket five int so it's an array of five integers we say equals and we uh say square bracket five and we give within the curly brackets they're actually five integers right so that's actually a way of initializing the array to a set of values to an array of five integers so that array of five integers that's uh inside the curly brackets that's actually called an array literal and we're uh defining x to be that to be equal to that array literal the length of the literal has to be the same as the length of the array so if you declare x to be five you better have five literals inside the inside the uh array literal uh now then there's this operation that dot dot dot that's actually a that's actually a keyword so dot dot dot is used to express the size you can use dot dot to express the size of an array literal uh you can do that because the because basically if you have an array literal and that and inside the curly brackets you have four elements in there then it's clear that you want this array literal to be size four right you don't have to say explicitly four so you can just put a dot dot dot in there and it will infer the size of the array from the the number of elements inside the array literal so in this example x colon equals in brackets we have dot dot dot we don't specify explicitly what the size is it says ant one comma two comma three comma four so it says four elements in there clearly you want x to be size four the most common operation programming operation that you do to arrays is to iterate through the array you know you look through each element of the ray and you do something with the element of the array maybe you add it to a sum or you check to see if it's greater than five or something like that but it is extremely common in programming to iterate through an array and check out each element in the array so um so the way you do that in golang is with a for loop so you can see in the code here we've got uh some sample array uh one two three right it's just three elements in it one two three now we want to iterate through the this array maybe we want to print out each uh each element of the array so we make a for loop now notice that that i have highlighted in there that range keyword right to the right of the range keyword is the name of the array that we want to iterate through so range x to the left we say for i comma v we got two variables here i and v i is the index of the array element that we're looking through in this particular path and v is going to be bound to the value of the array element that we're looking at in this past so the idea here is that in this loop if you look inside the curly brackets there's a print statement that print statement is going to get iterated once each pass through the loop so every path of the loop i and v are bound to different values i is the index of the of the element that we're looking at and v is the value so in this case uh with this array of the first pass through the loop i is going to be zero next pass is going to be one next pattern is going to be two right it'll increment each time and v is going to be the va the ith value in the array so the first pass through when i is equal to zero v is going to be equal to one because the first element in that array is the number one so the zeroth element is the number one then the next pass i is going to be one and v is going to be two because the first element the from zero one first element that count is the value two and so on and all this this uh this loop does it's very simple just prints out the i and the v together but that's the idea this allows me to iterate through the array so i and v get bound to an index and a value inside inside this uh this array on each pass and so inside the loop inside the the curly brackets of the loop we can do whatever we want to that value v right into that index i [Music] so a slice is a data type that you don't see in a lot of other languages the slice is a really useful data type so a lot of times actually slices are used instead of arrays because they're flexible you can change their size you can increase them in size so let's talk about slices and how they define basically a slice is a window on an underlying array so for every slice there's got to be some underlying array that is the basis for the slice the slice is just a window of it a piece of it so you've got a long array of 100 elements the slice is just maybe it's just three four and five or something like that a little illness or five six seven eight nine something like that that's basically what a slice is a window on a larger possibly larger array it doesn't have to be larger the array can be the same size as the slice right then the slice is just looking at the entire array but the array can be much bigger than the slice and the size can be just a smaller window on it so that's essentially what a slice is so slices have uh they can have variable size up to the size of the array this is one thing that's really nice about slices you can increase the size of the slice see an array is a fixed size thing so let's say i have an array of size 100 and i have a slice of size 10 which on that array and it's the first 10. i can increase the size of the slice to 20 and just look at the next 10 elements of the array and then i can increase it to 30 and include the next 10 elements of the array so slices you can increase the size of the slice where you can't do that to an array so that's a good feature of slices now every slice has basically three properties one is a the pointer okay that indicates the start of the slice so every slice since it's a window on an array it has to point to some element of the the array that is the first element that is included in the slice that's the pointer the next thing in a slice this property of a slice is its length it's the number of elements in the slice because they all have a length the third is the capacity so the capacity is the maximum number of elements in the slice now that's defined by looking at the pointer which is the beginning of the slice and looking at the difference between that and the side and the uh the distance to the end of the whole array because a slice its size can be increased up to the size of the hole up to the end of the array so for instance say you got an array of size 100 you got a slice of size 10. you can increase that slice's size say the slice starts right at the beginning of the array you can increase the slices size all the way to 100 if you want to so it has a capacity of 100 but say you got an array of size 100 but this slice starts at array index 10 right then it can only be increased to size 90 because by then you reach the end of the array so the capacity of that slice is smaller so let's uh look at an example to see what i mean by these things slice example so first we start with the underlying array we've got this array we define it uh with this literal um it's got let's see a b c d e f and g that's the array array of strings now then we define two slices on this with that array as the underlying array s1 and s2 now here's how we define these slices we say we use this bracket notation and we use the colons inside the brackets to define the beginning and the end of the slice so if you look at s1 s1 colon equals array arr bracket one colon three the one is the pointer to the to the first element of the array that is inside the slice and the three is the index just after the end of the slice so that slice s one it includes array elements one and two not three so the second number after the colon is just after the end now if we look at s2 that's two colon five right so s2 starts at two and include three and four does not include five so we can see this and uh we can see the picture down here at the bottom you got the array in blue the whole array and it has the abcdefg then uh in red i've highlighted s1 and s2 so s1 it includes index one and two right because one colon three so three is just past one past the end and s2 includes two three and four and notice that these two slices overlap and that's okay uh if you look at s1 and s2 they both include array index two right so and that's fine array uh slices can overlap and refer to the same elements inside the underlying array all right so the length and capacity uh so there are two functions len and cap which return the length and capacity of a slice so uh we got our array a one here and it's three elements long a b c then we define a slice uh sli one i'm calling it this time and that is the array zero colon one okay so that means that this slice includes array index zero but not array index one so it just its length is actually one should be one right it only has one element in it array index zero but uh so if we now in the next statement do the print statement we print the length and the capacity the length is one right zero and then zero is the only thing that's actually in the slice but its capacity is still three because it's uh because it could be its size could increase up to three if y increase the size of the slice to go all the way to the end of the array since the array has three elements in it and we're starting the slice at the beginning at array index zero we could go all the way through it we're into zero one and two and the length of the slice could be up to three so its capacity is three now accessing slices or really referring to slices uh so when you write to a slice to an an element in a slice you are writing to the underlying array and overlapping slices can refer to the same array elements so you change one slice you can change the underlying array and you can change any other slice that also accesses that it also includes that array element so here we got these uh in this picture we're showing this array we've got s1 and s2 or two different slices defined on it now see in green i circled that that array element two uh with the letter the string c in it right so that one is actually included in s1 and s2 now in s1 with respect to s1 that is the uh the s1 colon bracket 1 it refers to that second element to the array right because s1 0 would refer to the first element of the array because that's where s1 starts so s1 bracket 1 refers to that c that letter c now s2 that that or second element of the array is the first element in s2 so that's the same as s2 bracket 0. so these two print statements will print the same thing the letter c because s1 bracket 1 is the same as s2 bracket 0. they're both referring to the same element in the underlying array now we talked about array literals you can also have slice literals they can be used to initialize the slice just like an array literal can be used to initialize an array now remember that every slice has to have an underlying array so when you initialize a slice that means you're creating an array you have to create the underlying array and the slice just covers the entire array so when when you use a slice literal to define a slice you it actually creates an underlying array and it creates a slice to reference the entire array so the length and the capacity of the slice are the same right so the slice if you do this if you use it and a slice literal to create this array the slice will its pointer will point to the beginning of the array and its length will be the length of the array and its capacity will also be the length of the array so the slice points to the entire array when you use a slice literal to define in this way so we can see that here we're defining using a slice little rule sli is defined as a slice of literal and it defines the underlying array and you know that this is a slice literal because you can see where i say sli colon equals brackets normally in the brackets you'd put the length if it was an array or put 5 or 3 in this case or you put at least dot dot dot to say this is an array its length should be inferred from the um the number of of elements inside the curly brackets but in this case we didn't put anything in the brackets so the compiler says oh this must be a slice and what it does is it creates the underlying array and then it makes a slice point to the whole array [Music] so there's a function called make that can be used to make slices and you can make other things with it too but right now we're going to talk about make it slices so the one way that we made a slice the first one we talked about making a slice was just to make the underlying array and then make the slice after it also you can initialize the slice directly with a slice slice literal we talked about that this is the third way you make the slice uh make the slice directly but you're not initializing with any particular values so this is common uh this is when it's case like this where you don't you want to use a slice because it has this variable size ability and you don't care there's an array in the back right but you want to initialize the slice to a particular size so at least at the beginning so one thing you can do is call make it's uh there are two ways to call it you call it two arguments or three if you call it with two arguments the two arguments of the make are the um the first argument is the type so the type that of the are the objects that are going to be inside the slice so it's a slice of ants or slices strings or something like that that would be the first argument in string and then the second argument is going to be the length of the slice now when you use make to make a slice the length is equal to the capacity because it makes the underlying array and the array is exactly the same size as the slice so the length and capacity are the same so when you that is anyway when you use the two argument version of make so you can see here sli equals make we say bracket int to tell the type and then 10. so since i gave two arguments it figures okay length and capacity are the same so the underlying array is the same as the size same size as the slice and the slice points to the beginning starts at the beginning of the underlying array now the three argument version of make instead you specify the length and the capacity separately so that means that the underlying array is actually bigger than the slice so in this case we got sli equals make first we give the first argument the type bracket int second argument is the length of the slice the third argument is the size the capacity which is the size of the array so in this case our slice is size 10 but the array is size 15 so we can increase this slide this uh slice up to size 15 if we want to so uh there's an append function that can be used with slices and it's used to increase the size of a slice so if you want to add stuff onto the end of a slice and increase the size of slice in doing so you use the append function now note that this is a key advantage right compared to regular arrays that you see in regular languages you can't just add things to the end of an array and continually increase its size but with a slice you can so it adds the element the element the appended adds you can add one or more elements in this case we'll do one but it adds the element to the end of the slice uh and which means it inserts it into the underlying array so it increases the slice up to the capacity of the underlying array and it create increases the size of the array if necessary so if you reach the limits of the array size it'll all it'll make a new underlying array that's bigger so that you know so append never has to stop appending you can continually append even beyond the size of the array it'll just increase the size of the array you don't want to do that there's a time penalty for that but uh but it'll do that so as an example we make a slice sli we call make so it's size uh the size of the slice the length of slice is zero but the length of the underlying array is three so then uh so then i want to put something into the slice so the slice is empty right the size is zero so i say i append the number 100 onto the slice so i call append i pass the first argument i pass the slice the name of the slice and the second argument is 100 the number that i want to put into the slice so it puts it in in order to add that on it has to increase the length of the slice so now the slice's length would be increased to accommodate the new number that it put in there so that's how you would use a pen in general [Music] a hash table is a data structure used in a lot of different languages uh and it's a very useful data structure it allows you fast access to large bodies of data a hash table generally contains key value pairs so there are a lot of values inside this hash table but each value is associated with a unique key so for instance um maybe uh social security numbers and emails right so the social security number might be the unique key of the person and so that might be the key and then the value might be the email address of the person so that's a pair right a key unique key and value and the key has to be unique that's actually completely important uh also maybe uh like a gps coordinates an address right so every address has a unique set of gps coordinates coordinates associated with it so gps coordinates might be used as a key and then the address might be you know your house address right which may or may not be unique right where you live there are a lot of different street main streets in the world and there can be a lot of different one main streets so that might not be unique but the gps coordinates have to be unique or the key has to be unique in this case gps coordinates so uh ah so a hash table is meant to store these key value pairs and it is important that each key is unique so a hash function is defined and it's used to to take a key and compute a slot in the hash table to insert the value according to the key so you can think of a hash table with something like i hate to say it but think of it like a big array it's a got a lot of slots where you can put values in there right now which value which locate which slot it puts a value in is based on the key a hash function is used to process the key and generate the this number of the slot that you want to insert the value into so a hash function is a function that takes as this argument as a key and it returns the slot where you want to put the value now by the way this hash function you never call this hash function explicitly this is something goes on behind the scenes inside the go language but just understand there is such a hash function that does this so here's an example of uh what a hash table might look like so at the top we got this little table a bunch of keys and values so my keys are joe jane and pat they're all unique keys the strings are unique and here's some values x y and z they're arbitrary okay so joe is associated with x jane's associated with y pass associated with z and i want to put these three key value pairs into my hash table so if you look at the bottom you got on the right you got this uh basically an array right of some size and uh this is a small one but you know this is just an example so you got some array and the values x y and z are all placed in different slots inside this this structure so and i just placed them arbitrarily okay why isn't uh was it in in location one and x is in location three z is in location five right so they're in some arbitrary locations some slots inside the structure now then over on the left you can see the keys jane joe jane and pat now there in between there's this hash function and the hash function it takes the the key and genera it determines which slot it's going to place the corresponding value in so i drew this with the line so if you look at joe there's a blue arrow that goes into the hash function and then points to location three slot three so joe is associated with slot three which has the value x and then jane the hash function will compute a 1 in this case and so slot 1 has jane's value y and then likewise with pat pat is associated through the hash function with slot 5 and you put its value z inside slot 5. so this is the idea behind a hash table so uh the reason why this is good is something like an array or slice right you can access things in constant time but you don't have to use indices to access them you can use arbitrary keys right as long as the key is the keys are all unique and constant then you can use the key so i can so normally if this were an array if i want to access in entry one element one i'd have to say the name of the array and then brackets one in this case i can say brackets joe or bracket jane or bracket pat or something like that okay so that's actually useful the naming is useful for several reasons one reason is it's easier for a programmer to remember joe and jane and pat rather than arbitrary numbers right the numbers have no particular meaning with respect to the particular application you're writing where joe and jane and pat they are people and they have some sort of a meaning in the mind of the programmer so it makes it easier to code so advantages uh adventure is a faster lookup table than lists so this is an advantage as compared to like a list that you'd find in another language it's faster look up table lookup than list because in a list it's linear time lookup so that means if you want to find an element in a list you have to start the beginning list and go to the next and next and next and keep comparing until you find the one you want find one that matches that's linear time the longer the list is the longer it takes to find things in the list on average where this is constant times much more like an array right you basically you take the the index the key rather you use the hash function which takes some constant amount of time and it gives you the index and you go straight to that index so it's a constant time lookup rather than linear time like you would find in a list now another thing about it is that you can use arbitrary keys so this is better than say slices or arrays where you would have to use integers you can use arbitrary keys and those keys can have some sort of a meaning to them so disadvantages is that you may have what are called collisions inside your hash table so collision is when two keys hash to the same slot so joe and jane if they both if the hash function maps both of those to slot two then you have a collision then joe's value and jane's value both have to go into the same slot now there are ways to handle these collisions right there's a you can put them both in there and put them in a link list or something like this but it when you get collisions the speed gets a little slower right because those collisions have to be handled in some way so you don't have to worry about how they're handled that's built into go but that can slow you down but i'll say this that collisions are rare because the hash function is made in such a way that collisions are very rare okay so this is a possible disadvantage with collisions but it's not likely to cause you many problems [Music] so a map is golang's implementation of a hash table so map is is exactly a hash table you can use the make function to create a map so we have an example here so first thing i'm doing is i'm declaring id map as a variable a map variable right so i say var id map and it's going to be a map and notice it after the word the keyword map i have in brackets i have this the word string that's the type of the key and then after that i have another type and that's the type of the value right so the key and the value can be different types then uh line after that i so that first i'm declaring id map to be a variable then i'm actually assigning it pointing it to a map making an actual map and i call make for that so id map equals make and then parentheses map string int right so it creates a map now at first this make is going to create an empty map but it creates a map now another way to define a map is you can create the map with a map literal so you can initialize it with values with key value pairs rather so i'm showing that down here id map colon equals map string int and then in then i in curly brackets i list a bunch of key value pairs separate and the key and the value is separated by colons so in this case it's just one pair but you can have a comma separated list of key value pairs in this case it's joe colon one two three so joe is the key one two three is the value so and you can put any number of those you can initialize it with any number of those key value pairs accessing maps so how do you access the elements in a map at first actually most of it is the same as the way you would access an array except the index that you use that you put in between the square brackets that's actually the key so if i want to read read the value associated with the key joe i can say in this case i'm doing a print format dot print line l id map and then in brackets i say joe i give the string joe and it will that will return the value associated with joe and it'll print that i can also add a key value pair into the map or change an existing one if it's there so if i want to add some new key value pair i could say id map jane you know maybe there's no key jane in there right now i d map jane in brackets equals four five six so that puts a new key value pair in there now note that that would also change a key value pair so let's say there was already a key value pair in there jane was mapped to six seven eight right so i could if i by saying id map jane 456 i'm getting rid of the old key value pair associated with jane and i'm putting a new one in there so jane is now associated with 456. uh also you can delete a key value pair from the map uh so without overwriting it you can just delete it completely by calling the delete function so you call delete you pass it the first argument is the name of the map so id map second argument is the key that you want to delete so in this case joe and it'll eliminate that key value pair joe and the va joe and whatever its value is it will eliminate that from the map so there are also a few more map functions uh one thing that you can do with maps is you can have a two value assignment uh for a map so for instance here i'm saying id comma p colon equals id map joe now when i do that when i do that assignment if i had just done a single value assignment say i said id colon equals id map gel then id would equal the value associated with joe in this case i'm doing a two value assignment so the second value id comma p that p is going to be a boolean it's going to be true if the key is present in the map so there are cases where you don't you're interested in knowing whether that key is in the map maybe you don't even care what the value uh is associated with joe you just want to know if joe is in your map so p will be true if that key joe in this case is in the map and will be false otherwise there's also length function you can apply that to maps and if you do it you say like here i'm saying i'm printing len of id map it'll tell you how many key value pairs are inside the map another thing which is very common to do is to iterate through an entire map just like iterating through an array very common thing you want to iterate through every key value pair so what you do here is you're using uh basically a two value assignment with the range keyword so if it's a for loop so if you look at the for loop you got the key and then the value p comma value and then uh that colon equals range right on the id map so what that does is every pass through the for loop key is going to be equal to the one key inside the id map and val is going to be equal to the corresponding value in the id map so in this way every every pass every iteration through the for loop will will use one key and one value pair so q and value will be bound to a different key value pair for every iteration through the for loop and you'll iterate through the for loop until you've gone through every key value pair inside the inside the id map [Music] so a struct is another aggregate data type another composite data type it's an aggregate type meaning it groups together uh objects of arbitrary data types into one object and uh and it's useful for a lot of things usually it's for organizational purposes it really helps so let's give an example easiest way to talk about it you got let's say you want to make a struct struct is short for structure by the way and by the way this is taken also straight from say c c structs too so say i want to make a structure that describes a person a person struck so say every person has certain features a name an address and a phone number so i so for every person i want to represent these three different aspects of a person so one option would be to have three separate variables for every person i have three separate variables and the programmer has to remember that they're related so maybe i have name one and i might use naming for that so i might say well name one address one phone one i have three different uh values right and i put one after all of them so i as a programmer can remember okay this is name one and address one and phone one they must be related they all have one after them right and the next person i make i'll call it name two address two phone two and so on so uh so that's one way and in that that scenario these three pieces of information name address phone they are related uh they have to be the programmer themselves has to remember that they're related okay that this name is related to this address in this phone where this other name is related to this address in this phone now another way probably better way to do this is option two is to make a single struct uh that represents a person and that struct it aggregates all three variables so this one object now contains a name address and phone number of one person so they are related because they are in the same object and so when you're accessing them it is obvious that if you're accessing them from the same object you know that they are related to the same person so that's what a struct is for for bringing together different variables that are related in the application and putting them together so that you as a programmer know that they are related and they're related to the same person or whatever the object is in the application that you're talking about so um here's an example of a struct you've got um so we're defining a type a struct type and we're going to call it person and this person has three fields three pieces of information a name address and phone number so notice how i'm defining this destruct type it's called person i give it its name is a person and each one of these fields name address and phone has a type name string address string phone string after that once i define this type i can define any number of persons right i can say var p1 is a person rp2 is a person and so on and p1 in this case it's going to have a name address and phone number all its own so each property is called a field so name's a field address is a field phone's a field and p1 can have values for all of those fields that are unique from another variable p2 which is a person or p3 so i can have any number of persons in there so if i want to access the fields of the structure by access i mean read from them or write to them change them i use dot notation this is not like with arrays with arrays you use the square brackets and use an index you use dot notation here so p1.name if i want to assign that to joe i can say p1.name equals joe and that will assign the the field the name field of p1 to the string gel also i can read in the same way i can say x equals p1.address right and that will assign x to be the address of p1 so use dot notation rather than the brackets that you would use with with arrays initializing structures you can initialize them using a new function one way to make a sort of an empty struct it initializes all the fields to zero zero values so like in this person structure the the values are all strings right so the zero value is going to be empty string so i can say p1 colon equal new person and it'll make a new person that's empty it's all zeroed out so the name address and phone number will all be empty string another way you can initialize the structure is you can initialize it with a struct literal so if you want to give values to all the fields right when you create the person you and we're showing that here p1 colon equals person then in parentheses i'd give the struct name the excuse the struct name and then struct value right so uh name colon joe comma address colon a dot st right a street uh and then comma phone colon one two three right so in this case i'm using a struct literal and i'm making a new structure but i'm also assigning all the um the fields to different values joe and a street and one two three so i can do that too [Music] welcome to module four we're talking about uh protocols and formats in this module standardized protocols and formats so the idea here is that when you write code you it is very common to want to interact with other systems outside of your own code and when i say interact i mean trade data you get past data to the other system it passes data back to you this happens all the time maybe it's networked you're communicating with some network network server or something like that maybe you're just trading data files you know you have a database and it's in a particular format you want to give that to another piece of code another system or you want to accept a database format provided by something so in order to do this type of communication interaction between different systems there are many standards that exist standard communication protocols and standard data formats that exist that allow you to communicate with other systems html json there are a ton of them and we'll talk about some of these and golang has packages that that handle they that allow you to interface with these standards not all of them but all the big ones so html there's a package just for dealing with html json there's a package for that and so on so we're going to talk about some of these packages and you'll be able to use them inside your code and communicate with other bigger systems [Music] so uh an rc is a request for comments uh that's technically what it means but what it really is is the definition of a protocol or a format a standard definition now reason why we're concerned with these they're not part of golang directly but whenever you write a big program you will to do something you're going to want to interact with other systems other blocks of data somehow i mean it is extremely common so for instance maybe you want your program to um read files read database files and uh process them right so these database files they maybe they came from some other source you know uh some data maybe somebody inserted them on the web ad added to my sql database and you want to be able to read those files right so there's got to be some format that everybody agrees on that you can communicate through so you know this is going to be in this particular format and your code can process that format uh same thing goes for maybe it's a network protocol right so maybe your your machine maybe you want to do a client server thing right so you want you want to make a web client and your web client needs to talk to a server over the network and in order to talk to a server it's got to send messages in a with that adhere to a particular protocol so the server understands what it's getting and then on the other end on the receiving end your machine your program has to be able to understand the format the protocol of the message that it receives in return right so whenever you make some kind of a bigger system and it needs to interact with other systems through data transfer this data has to be formatted in a way that everybody understands it say so there are many of these formats and protocols that are well defined and are standardized and used for communication and trading data between different systems there are many many of them and rfcs are uh are the the the name that are used for for these these um these pro a lot of these standards now they're non-rsc based standards but rc's are a sort of a broad swath of standards so for instance uh let's give you some examples take html hypertext markup language html is the language in which web pages are written so it's a standardized language actually it's rfc uh i got the rc number right there on the slide and it's a standardized language uh so that all clients all web browsers they have to understand this language so they know how to render it on the screen and so on so that's one of those languages the standardized and you can trade data between a client and a server between a web client web server using this standard uh also uris right these are also there it's an rfc too uri stands for universe uniform resource identifier it's uh basically the the addressing method used on the web right so you've heard of a url this type of uri so there's a particular format in the way that it's supposed to see and that it's got to adhere to a particular format so that every client every server can interpret the the address http that's a network protocol web-based web network protocol defines the web uh hypertext transfer protocol okay and that's rc 2616. and that describes how the messages should be transferred on the network so what the what information should be included in each message and what the headers are where the data should be the content and so on and the length stuff like this that's all defined so that a client can talk to a server a web browser can talk to a web server or something like that so these are just a few of the protocols of these standard protocols that are defined by rfcs and there are a lot more and these protocols can be arbitrarily complicated some of them right some of them are simple some of them are complicated and so what happens in goaling in language like golang they provide packages that help you to process these formats a lot of these not all but a lot so there are packages for most of the important rscs there are packages already built that you can incorporate you can import into your program so and these packages they provide a set of functions that you use to encode uh encode data into the into whatever the protocol is the format is and also to decode right so if you're receiving something in a particular format from some other source you need to decode that information into into structures uh maybe structures or maps or some kind of um golang objects right and the other an encoding is the other direction where you take some kind of go objects and you convert them into this this common protocol or format so as an example there's a net slash http that's for that's for http hypertext transfer protocol and they you have that package and it provides a bunch of functions in there that i allow you to make uh to make messages and send them so for instance i've got this example http.get that makes a get message you pass it as an argument a web domain and it will make a request of that domain for a web page and it'll return the actual content of the web page for you right so there are a set of functions like that defined in this package that allow you to uh to communicate over the web right and send uh send you know so if you want to make a web client or web browser web server or something like that you would use a package like this another package a more basic one is the net package and this is for tcp ip and socket programming so this is sort of a long description but tcpip basically define the internet so internet you can do web-based communication on the internet but you can do all kinds of communication protocols over on the internet ftp secure shell is a whole list but all of them share in common this basic tcp ip udp stack uh the set of protocols they all have to adhere to and so the net package gives you a set of functions that allow you to to use that protocol so for instance this example here net dot dial tcp says look i want to make a tcp connection and you give it the domain uci.edu colon80 tells you the port number you pass that and it establishes a communication a connection internet connection tcp connection specifically with uci.edu on that particular port which happens to be a web port but uh so there are a lot of these packages that are used to support to make it easy for you as a programmer to use these different protocols communication protocols and data formats that are commonly used across by different systems and it's just a there it's just a very useful thing to have these packages and to use them because when you don't have them you have to do it from scratch meaning you have to for parents to take http if i didn't have the http package i would have to understand everything about http and make the packages on my own i have to basically make the message format and my own i have to write my own code to do that now this is not impossible but it is time consuming why do that when you can call http.get it makes it a lot easier for you as a programmer so json is one of these protocols it's a it's not a protocol it's a data format commonly commonly used data format across the world and we're going to talk about that and the package associated with it so json stands for javascript object notation we are not programming in javascript but json is bigger than javascript now json is it's just widely accepted as a common way to represent structured data it's rfc 7159 it's a format to capture structured data and by structured data i mean a set of attribute value pairs so this is a natural uh a natural for a struct or a map right because if you remember structs they have key they have not keys they don't call them keys they have uh fields and values of the fields right so a field value pair could be an attribute value pair in json or a map has key value pairs right that's the same that can easily be an attribute value pair so these attribute value pairs and json sort of naturally map naturally i shouldn't use the word map they naturally correlate to structs and maps inside inside golang and now the keys and values or rather attributes and values as they're called in json they can be a basic value type so you can take you know boolean numbers strings arrays objects and they can be combined um hierarchically so it's easier if we see some examples of this so uh let's take an example of a uh start off with a ghost structure right a ghost struct uh the person struck that we had before right so this perfect person structure i'm making p1 i'm saying p1 is a person with a name of joe address of a street and a phone number one two three so that that uh that information maybe we if say we wanna transfer it to another machine somewhere else okay we're gonna give it to somebody so we want to take it from you know right now we have it represented as a structure and go we want to represent in this common json format so that somebody else some other program some other system somewhere can interpret that so what we're showing below is the equivalent json object so up above you see the struct as we would define it in in go and in json this what it would look like as a json object is shown right there and notice this is very similar to the structure to what a struct looks like or what a what a map looks like it's basically name colon joe address colon a street phone colon 123. now one thing to note is that the name the field names the attribute names name address phone they're in quotes right which they weren't when we defined the ghost structure we didn't put them in quotes so it's a little bit of difference but notice that it looks very similar to the struct right so that that json object we can take that and pass that on to some other machine some other program and if they can interpret json then they can extract all the information that we were using in our program about this person and this is of course one person but i could have a database full of people and i could just make a set of json objects passed to somebody and they could read this database full of people so this is just a sort of simple example of json but json is actually nice and it's a it's a good format it's well accepted [Music] so json as a format has several properties that are advantageous one is that it's all unicode okay uh so any json object once you convert something into json it's going to be represented all as unicode characters which is good because unicode is understandable by people in fact that's at least another thing is generally human readable right it's a human could look at the json format and and understand for the most part what it is it might be slightly complicated but it's readable by a human now it's also a fairly compact representation i say fairly compact because it's not completely compact if it were the most compact then you wouldn't be human it wouldn't be human readable anymore so if you took the json object and just compressed it you would get something that was smaller but you couldn't read it okay so it's fairly compact it's human readable it's as small as you're going to get and still be human readable put it like that and uh so the types inside json can be combined recursively when i say the types the different types of data that that you're putting together so remember that in json we're going to want to represent these different data structures that we have these objects that we have in in golang we're going to want to represent them as json objects so they can be combined recursively so you can have an array of of uh integers or or an array of structures or a structure with structures inside or a structure with arrays inside and integers and strings so you can combine them all hierarchically right a structure with structures inside which have other structures inside and so on so you can get arbitrarily complex golang objects and convert them into json so that's a pretty good advantage so json marshalling marshalling the term marshalling means to um in this case in json marshalling you're generating json a json representation from an object in our case a go object right so we've got some object arbitrarily complex in go we want to make turn it into something that adheres to json format right so that's called marshalling json marshalling so in this example we're going to start off with our person struct uh and here's our here's the general structure type struct's got a name address phone they're all strings and this is the structure so let's say we create a we have an actual person an object of this a particular structure of this type and uh and this person p1 it has a particular name joe address a street phone one two three we've seen this before so now we want to take this person destruct and we want to make it turn it into a json object so we call this function json marshall json.marshall and notice that we passed as an argument we passed p1 the the structure the golang structure that we want to convert we pass that as an argument to json marshall and it returns two things in this case they're called br the first thing is b array i'm calling it and next is error so uh the error is it's a nil if there's no error if it converts properly then this should be a nil there'll be no error and what the real what returns this b array is actually going to be a byte array which it contains uh the json representation so and remember that json is all unicode so this byte array is a bunch of runes basically uh see an array of them and that that is the that is the json representation so so what marshall does json.marshall does is it takes a golang object returns you a json representation so json unmarshalling is going in the opposite direction uh what you're trying to do is you take some byte array which represents which contains a json object and you want to convert that into a golang object right which stores the same information so going from the last slide we're again talking about this person struct so let's say we have already made our b-a-r-r our b array and that's a person okay it's a json representation of a person now we want to unmarshal it so we want to take this json representation and create a json excuse me a golang struct which contains the same information so what we do is we declare that golang struct up there at the top we say var p2 we call it p2 person so it's a person but we haven't created it yet we haven't filled in the name address phone yet so we just have a person and it's basically empty then we call json.onmarshall now notice there are two arguments were passed into json.on marshall first argument is the b array which is the actual byte array which contains the json object the second argument is the address of the go structure that we want the results to be placed into so address of p2 because remember that this b array it contains information about a person we want that to be put into this p2 that we've created that is as of now empty so when you call it it just basically unpacks the b array and puts the fields into the appropriate they attribute values into the appropriate fields of the person structure p2 now one thing about this is that uh one constraint is that this p2 whatever the second argument is to unmarshal it needs to fit the json data the json byte array when i say fit i mean the json object is going to have a set of attributes and values of those attributes p2 the second argument it's got to have the same attribute so if it's a struct in this case it's got to have the same those have to be the the field names so if the the json object has an attribute called name then the uh the golang object p2 it better have a field called name right so that's the idea uh so it has to fit uh but if it does then what will happen is you call on marshall and in the end p2 will have will contain will be a struct that contains all the information that was contained in the json object and that error value that's returned by json.on marshall it's nil if everything works everything fits if it doesn't fit it'll throw an error thank you [Music] so files are very commonly used in programs and used to trade data between programs so we're going to talk about how how golang allows us to access files we'll give an overview anyway now file access and this has this is true in in all languages file access is linear access not random access so the reason for this is because files when they were originally defined they came from uh they were actually stored on tapes right physical tapes and when you access a tape like you remember depends how old you are but you know i used to have cassette tapes right so or big old tapes you've seen them in movies science fiction movies big old tapes right they turn this physical tape that it's on and it's linear access meaning the beginning of the file is at one point in the tape the end of the file is way over here at the other point of the tape and so if you want to access it you got to start you read one point of the tape then you got to turn the tape and read the next point turn the tape read the next part and so on so it's always linear access wherever the the turning limits it right there's this mechanical operation of physically turning the tape to access the next piece of um the next piece of the file right so it's so it's always linear access if you want to just access something at the beginning then something at the end that would waste a lot of time the beginning is here then you've got to take a lot of time turning to get to the end right instead you read it linearly you say okay i'm at the beginning and i read the everything in that vicinity you read from the beginning to the end so that's how file access still is today even though you don't necessarily have this linear access constraint i mean if you look at physical disks they still have linear access right you sell tracks uh and you have to go through the whole track so there's still some linear access in that but you know for all we know a file might be might be in a random access device so for instance a flash memory or something like that solid state drive right that's actually a random access device but we still the way that we access files in programs is as if it's a linear access device so uh so normally when you access files you get in other languages too you get these set of basic operations that are sort of common for file access so first one is open it's getting a handle test start accessing the file you have to open the file first then you always get a read function or some variety of read functions where you can read bytes from the file and read them into like say a byte array write where you write data from a byte array and move that into a file close is when you're done you close the file because you're done reading it or accessing it and then seek is another thing a common thing to have seek basically moves your read head so what that means is uh it's linear access right so you read from the beginning to the end but sometimes you really do need to skip to a certain point and seek does that so these are very common functions that you see basically in any language to access files so uh there is more than one package in go that allows you to access files it has functions in it that allow file access we'll start with the i o util package i util package has some has some sort of basic file access functions basic uh they're easy they're nice to use if the basics are enough for you ioutill is great so uh the first function you get there is a read file now read file you'll notice that ioutil.read file it takes an as an argument the name of the file you want to read that can be arbitrary you know test.text or whatever you want to call it and it returns two things data uh basically a byte array and then an e is the error right so it returns two things an error is only if there's some kind of error reading but if there isn't an error its main job is to return this byte array which is the first thing it returns so and what it does is pretty simple it just reads the whole file and returns the contents of the whole file into a byte array and then you can manipulate the byte array now when you use read file you don't have to do an explicit open or close you don't have to open the file at the beginning close it at the end that's all built into the read file function so it'll just open the file read the whole thing and then close it so it's nice one issue with it is that large files can be an issue so when i say causes a problem it's not going to cause an error but files can be gigantic okay you can have i mean if you think about the size of a disk you can have the disk can be you know a disk can be terabytes right i mean i have a terabyte disk in my machine right and that's not that's normal right so you can have giant size files you can have files that really take up most of your memory because when you read a file it takes it off of whatever the storage device is let's assume you're using disk for a second okay say i put it on disk but it could be solid state storage too it takes it and it reads it into ram into into its main memory now main memory is much more limited so my disk i might have you know a couple of terabytes but my ram i might only have eight gigabytes so i could have a file an eight gigabyte long file on in my disk that i try to read into main memory if i read that whole file i'm using up my whole ram and my machine will choke okay i can't run anything because i've used up all my memory so when you have large files read file is uh you can't use it okay so if but if your files are smaller small enough so that it doesn't hog up all the memory uh then then then refile is fine you know you can just read the whole thing in at once uh now i o util also has a write file function which is complementary to the read file and if you look at write file it takes uh actually it takes three arguments first argument is the name of the file you're going to write to the second argument is the byte array or as a string and then the third argument is the permission so remember write file it's actually creating a new file so when i call right file here i'm going to create a new file called outfile.txt and it's going to write the data hello world into that into that file when it creates that file it has to give that file permissions you know read and write access permissions so it's using unix style permission bytes so 777 means permissions for everybody right everybody can do everything basically but you can adjust the permissions as you see fit but those are the arguments to write file so again it writes uh now remember with write file it's not flexible you can't append to a file or something you can't say oh let me just add on to the file write file it just creates a file dumps everything the whole string or the whole byte array into that file and then close the file [Music] so uh when you're accessing files we talked about the ioutil it gives you some simple functions but if you want to have a little bit more precise control over file access then you're probably going to use the os package the os package provides a bunch of functions to access files too and you can access you have more control so with i util you could read the whole file and write the whole file and that was about it with os package you can do a little bit more read a little bit write a little bit do different things so uh here are some of the functions in there first you got os.open that opens a file so you you pass it a um the name of the file and it will return a file descriptor a file a file struct basically uh call it f let's say and return a file descriptor that you can use to access uh the file now os.close it closes a file when you're done os dot read reads from a file into a byte array okay now and it reads to fill the byte array so you can control how much you read unlike with read file and i o util you had to read the whole file if you only want to read 10 bytes out of it you can make a byte array a size 10 and pass that to read and read will fill that byte so it'll read 10 out read however much you need to fill the byte array and write a similar thing you can take a byte array and write that into a file and it'll just write as much as the byte array is long so here's an example of file reading using the os package so uh first thing we do is we open the file so we call os.open passes the name of the file which is completely arbitrary so we pass this file name dt.text it opens it it returns this f this file handle that we can use to access the file and an error if the if there's an error like the file doesn't exist or something like that then it'll throw an error but otherwise it'll return this file handle now uh now i'm going to for this file i want to read right i want to read into some byte array so let's say i want to read 10 bytes out of this file so i can make a byte array b array colon equal make i call make i could make it a byte i give it the type and i say comma 10. so now i have this byte array empty byte array then i can call f dot read f is the file handle that was returned by open call f dot read pass it the byte array as the argument and it will then fill that byte array with the first 10 bytes out of this file now note that if i called it again with that same byte array it would fill the way with the next 10 right every time it would it would the head the read head actually moves so the first i read the first 10 if i read again it's not going to read the first 10 again it'll read the next 10 until i close it and it resets the head this function returns two things an error if there's an error so if you're trying to read something and you're out of space there's you know it's empty or something like that you reach into file you might throw an error but otherwise it returns nb which is the number of bytes that it read now sometimes the number of bytes should be equal to the size of the byte array but it doesn't have to be you can have what's called a short read maybe the binary is size 10 but there are only five bytes left in the file then you'll only read five out so nb would equal five in that case and then when you're done reading you just call f dot close and it closes the file and resets the head for the next time so next example is uh right this time using the using the os package as well so first thing we're going to do is we want to write a byte array into a file so we first create the file in this case os.create we could have opened the file we could have opened the existing file and opened it for append to append to it but in this case we're just going to create just for an example we're going to create a new file call it outfile.txt and then we get this file handle f that refers to that file then we make a byte array with using a using a um sorry we make actually this is a slice but we make a slice by we're calling it b array but it's a slice has three elements in it one two and three we want to write these so we call right f dot write we pass it the byte array and it just writes those three bytes into the file now another thing that we can do there's another function for writing called write string that takes an entire string instead of a byte array it takes an explicit string and writes that so you can call right string and hi or something like that pass it a string it writes that into the file and which has to be a unicode sequence
Info
Channel: freeCodeAcademy
Views: 46
Rating: undefined out of 5
Keywords: Getting Started with Go Full Tutorial, go programming language, go programming language for beginners, go programming language tutorial, go programming 2021, go programming language web development, go programming project, go programming course, go programming android, advanced go programming, go programming by example, go programming basics, go programming bootcamp, go programming blockchain, go programming for beginners, go programming challenges, go programming code, php, js
Id: OeZ0-iuA6QA
Channel Id: undefined
Length: 188min 46sec (11326 seconds)
Published: Mon Nov 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.