Next lesson playing in 5 seconds

  • Overview
  • Transcript

2.6 Pointers

At a high level, one of my favorite features of Go is that it also takes features of languages from the past that most high-level languages of today don’t expose. In this lesson, we will discuss pointers. It’s a topic that can initially sound daunting, but with a little time and thought, you will be using pointers like a pro.

Related Links

2.6 Pointers

Well there comes a point in every software engineer's life where we have to take a little bit of time to pay homage to our predecessors, especially when it comes to programming language. And that day for us, well that's today, because we're gonna talk a little bit about pointers. Now if you're used to a lot of the high level programming languages that have come out over the last several years namely, Java, and C#, and things along those lines, you probably don't hear too much about pointers because a lot of that stuff is masked and done underneath the covers, and you really don't see it very often. But that doesn't mean it's not important, and it's something that we could definitely find useful. So Go, while it has a number of new features incorporated into it, it definitely has this flair for where we came from, and that's one of the most endearing features of it, at least from my perspective. So what I wanna do now is I want to talk a little bit about what pointers are, how to use them, and some of their benefits. So the first thing is what exactly is a pointer? Well if you think about it in terms of the resources you have within your computer, you're typically talking about your CPU, your processing power and your memory. So every time we create a variable, we're allocating space in memory to contain or to hold that value, and there's two pieces of information that are typically associated with a variable. You have the data that's being stored and you also have an address to that specific place in memory. And what a pointer allows you to do is to more finely grain separate those two things out to be able to get access to both of those pieces of information. So what exactly does that look like? Well let's break it up a little bit. So the first thing that I wanna do is I wanna create a simple variable called num, and I'm gonna initialize it to 50. So we have an integer type here, and it starts off with a value of 50. And now I'm gonna create a pointer to this variable. So a pointer, remember, is going to contain a memory address that's gonna point to this particular value that we're holding here. So the way that we do that in Go is, we're going to specify the names, once again, it's gonna be a variable like anything else. And we're going to initialize it to a pointer to whatever is stored at num, and the way that we do that is we use the ampersand sign and the name of the variable, so I want to create a pointer to this variable. So let's go ahead and save that, and now I want to actually print out what these values are. So let's do a little bit of printing here and I want to say that num = and we'll do a little string formatting here, and we're going to use the %d to say I wanna put a digit out here. And this is going to be num. And let's save that, and then we'll do one more print F. And in this case I'm going to say that the pNum, and actually let's take that back just one step, we're gonna make this a print line. And what I wanna do here is I want to print out the value of pnum. So let's go ahead and save that. Now one thing I wanna do here too is that since I'm using print F there's not a new line that's gonna be appended on the end of the string by default. So I need to put it in there manually, and the way that we denote new lines in go in many other programming languages for that matter as a /n. So you're gonna see that this is gonna put these two things on separate lines. So once I've done that, I'm going to run Pointers.go. And I'm gonna get two values here, I'm gonna get num = 50, which is exactly what we would expect. And the second Println for pNum gives us this very strange value. Well this very strange value is actually the memory address where we can find this value right here of 50. So what does that mean and what can we do with that? Well we can use it in two ways, we can use it as an actual address as you can see here, or we can get access to what is found within that memory space. So let's change this a little bit. We're gonna change this to a Printf, and we're gonna say pNum is gonna be equal to, and I want to get the value that is stored at that location, and the value stored at that location is 50, but how do we get that? Well the way that we get the actual value at a pointer location is using a star. So we're gonna say star PNum. So if we want to create a pointer I use an ampersand and if I want to get the value add a pointer I use a star. So let's go ahead and save that and we will once again run our command and you see that num is equal to 50 and so is pNum. Okay, that's pretty cool, but what does this mean? What does this have to do with anything? Well, because I'm using a pointer, I'm actually using less resources and the storage space that it takes to contain these values is less. So I'm not allocating space for the number 50 here, and as well as the number 50 here, I'm allocating space for the number 50 at whatever address space is held by num, and then I'm simply creating another pointer that is taking up much less space and simply pointing back to the same value. So if we do that, and I wanna to get access to pNum, I can treat this just like I normally would and I could set this equal to say 45 now. Save that result, and actually what I'm gonna do is I'm gonna grab these two lines, and I'm simply gonna print them again down below, add a couple more new lines here. Save that, and now if I run this again you might be surprised if you've never seen this before as what's gonna happen. So if I run this again, initially the value for num is set to 50, and the pointer to that location is set to 50, but then if I change the value stored at the pointer, pNum, to 45, it not only changes the value that it's pointing to, but it also changes the original value. So, as you can see I now have two pieces of information that point to the same place. And it works the other way as well. So if I change num to be equal to 600 and then once again do the same thing, and save, I go and get both values, you see they both change. Now what's the point and why it with all the parlor tricks? Well the parlor tricks are just demonstrative, really the major benefit of this is speed and resource utilization on your system. If you're using pointers properly, then you are able to take up less memory and your application can save that amount of time that it takes to allocate space to store variables and store values at variable locations, and then have to pass those things around. Now whenever we create a variable and then say pass it into an argument list for a function, we're typically creating a copy there, we're having to copy that location into an address space with another value that can be accessible within the scope of that function that we're just using. But if we're passing around a pointer, we don't have to worry about creating copies of data and taking up more resources. We can simply pass in a pointer. And that's typically where you're going to see the benefit of these pointers, which you'll see in an upcoming lesson. So let's see an example of that. Let's create a function, we're gonna call this increment, and in this case I don't wanna send in a number, I wanna actually send in a pointer to a number. So how do we specify a pointer type in an argument list? Well we specify the name, so we're gonna call this number. And then in order to give a pointer type, we use star, and then the type that is going to be passed in for that pointer, which in this case is gonna be an integer. So in this case, what I wanna do is I want to get access to the value that store int num. And I want to increment it. So let's save that. And I think we could probably get rid of a little bit of this extra space here. We'll save that and then we can clear out this. Okay, so now what we have here is we have our increment function which is gonna take in a pointer to an integer and it's going to increment that value. So what do you think's gonna happen if I create a variable that is a pointer to our number here, and I pass this pointer into our increment function? Well let's give it a try. And what I actually wanna do here is call my Increment function, passing in my pointer. And then once I'm done, I want to do fmt.PrintLine. And I had to add that import statement back in. And then I wanna print the value of number. So let's go ahead and save all of that. And we'll run our application. Go run pointers.go. And as you can see I created and initialized my num variable to be 50, I created a pointer to it, I passed that pointer into an increment function, and I did not return anything. And because I'm not returning anything, I'm simply passing in an address space, and then within my function I'm getting access to that actual address space and then changing its value, I get access to what is actually stored at that address location, both inside and outside of that function. So that is pretty cool stuff. So as I mentioned before, Pointers can be a very daunting thing, but if you really take your time and pull it apart a piece at a time, you start to realize that when it comes to dealing with variables and the data that store there, we're talking about two different pieces of information, we're talking the data, and we're also talking about the address space. And if you're able to use these things in conjunction, in a very intelligent way you can really make some very performance applications and that's definitely one thing that Go is very good.

Back to the top