Check out a free preview of the full Basics of Go course

The "Pointers & References" Lesson is part of the full, Basics of Go course featured in this preview video. Here's what you'd learn in this lesson:

Maximiliano showcases the usage of pointers in Go, which allows creating references to the original value of a passed variable. It's important to note that unless a reference is used, Go automatically creates a copy of the passed variable.


Transcript from the "Pointers & References" Lesson

>> Let's work with pointer for the first time. I know it sounds scary, okay? But let's think about this. So I have a variable, I'm going to create a variable that says I know my age. I will say that I am 22. Yeah, I'm 22 you can see that, it's complaining because I'm not using the age.

And let's say that I'm going to format Println that age, but then I have a function with a name birthday that receives the age as an integer. And it's saying ++, ++ is the same the same as + = 1, and is the same as age = age + 1, shortcuts, okay.

If you're coming from other language, probably you have seen that before. So let's run this. And it says 22. Let me remove all the a, and b, and other stuff that we have there that we don't need. Also, yeah. Okay, yeah. So it says 22, cuz we have a 2, I don't know where that's coming from, but it's 22.

Why? 2 move the age, right? So because I'm saying age + 1. Well, maybe you're saying, hey, you didn't call birthday. Okay, you're right, so someone is still awake. Okay, cool. Let's see. Go run, 22. But let's say maybe it didn't execute, so let's call it a couple of times.

It's still 22. Why?
>> Because it cloned it when it passed it into the function.
>> Exactly, because it's cloning the value, it's passing the value as a copy. So when I'm calling birthday, actually, it's creating the variable of the 22 and passing that copy. And we are incrementing the copy, not the original variable.

A lot of people would like to see something like that in the real world, right? But when it's your birthday, it's someone else that is counting years and not your age. So that's why it doesn't work by default because every argument is passed automatically here as a copy.

So to deal with that, we can receive instead of an integer, a pointer to an integer, it's like a reference to that integer, okay? And that's a star, it's a star before the type, it's a pointer to an integer. It's not the age, it's like the phone number of someone that has the age inside, so then you don't have the object, you have a reference to the object.

So now we are talking about the same age. And by the way, now it's giving me an error because, hey, I cannot pass you the value, I cannot copy the value, I need to pass the reference to the age. And for that, we use a prefix of an ampersand.

That is like the counterpart of the star, okay? I know it feels we weird, we will see a couple of examples where this makes more sense. Now it's giving me an error here, because saying, hey, you cannot do a plus between and *int and an int because now age isn't *int, okay?

It doesn't make sense, so then we start thinking, okay, maybe this, maybe that. What should we be doing here?
>> To reference the value.
>> To reference to the value. Yeah, so what about ++? Is it still giving me an error? So why? Because now we have a point, and this is trying to make it + 1 over the pointer.

And that's not what I want, I wanna get to the object, I'm saying object, but we know it's not really an object. We are going back to the integer, and we want to apply something, some change there, okay? So is it the address of that? No, it's not the address of that, it's actually star, we use a star here.

It's like let's call the h, I don't have the h, let's call the h, and the h will do the ++ under real numbers, okay? Does it make sense? Here it's complaining that I have a function that I'm not using. But anyway, if I run this, I'm 23, so birthday worked.

It's a little obscure at first mostly if you haven't heard about pointers before, but this is the most difficult thing you will see. And we will use it a couple of times, and you need to use this every time you have a function that is going to modify the arguments.

So if the function will modify the arguments, the incoming arguments, those arguments must be pointers. Because if not, you will get a copy and you will be modifying the copy, not the original one. That typically makes no sense. Okay, yeah. It's not getting more difficult than this, pointers with Go.

>> I can't remember if I'm remembering this correctly, but doesn't JavaScript sometimes point something that's a pointer? If you pass it an object, then you have to prevent it from mutating that object. But if you pass it a string -,
>> In JavaScript, when you are passing objects, you are passing the object by reference, so you're doing this by default.

>> Yeah.
>> And not with numbers, with objects, with object. So if you try this with numbers, you will also have a similar problem. But yeah, and that on JavaScript, then you have a way to phrase the object or to clone the object in case you need to clone it.

So in every language, you need to first look into the details to see if arguments are being passed by value or by reference, it depends on the language, actually.
>> I kind of like that you have to be so intentional about it, and all of a sudden have no idea why your object just changed a bunch.

>> Well, so here the the rule is simple. It's by default, it will be by value, it could be a copy. So if the function needs to change the arguments, you need to receive a pointer. I know you say, but I have to use this ampersand and the star, it's just that, it's not really so difficult.

I think the birthday example is pretty straightforward
>> Why do you not have to use the ampersand in front of the age when it's here too?
>> Because age is not an integer, it's a pointer of an integer. And here age, we're using the same name, so it feels it's the same variable but it's not.

So, in fact, we can change that, we can say this is the point, we call that pointerAge, okay? Let's do this. So in this case, this is the pointerAge. When we use a star, we go to the age, to the age that we have. And then when we have the age, so it's like wrapping and unwrapping this, right?

If I use ampersand here and not star, I'm getting the address of the pointer. That is, if you wanna get a pointer of a pointer, this is one goes forward and the other one goes backward. So if you use ampersand here, you're going backward twice, something like that, okay?

So it's like wrapping and unwrapping, boxing and unboxing, so you have one that is boxing, another one is unboxing.
>> I was actually, the printIn when you mapped out printIn.
>> Here?
>> Yeah, and you're just referencing age, you're not referencing -.
>> Because age is a number and I wanna print a number.

If I do this, I can do that, and we can see what what happens. Can I print that? Yes, I can. And what I'm getting is that thing, that weird thing. What's that? That's a memory address.
>> Got you.
>> That's a memory address of the edge is where that variable say it's in memory, it's the address of memory, okay?

But I don't wanna print that, I wanna print the age. And when I'm here, what if I print, let's print pointerAge and see what we have. Infact, let me also take my main. Let me remove that cityTax part. So we see only what we want and also this.

So we keep only this part. So this is what I'm getting. So if I print pointerAge, I'm getting also the address. If I'm printing *pointerAge and printing the age when I have to, because I'm also printing here. So there is a printIn, so you can see we are talking about two different outputs, 22 and 23.

And in fact, can you see that when we are sending output to the console, sometimes it's difficult to actually find which output is for each part. So, so far, I mentioned that we should be using format and there we have .Print or printIn, but also there is a third one, Printf.

If you have ever played with C-based language or even with C actually, probably you know what F is for, but F stands for format. And you probably will like this. This is a template string. This is like a string format on Java. This is like a template string with a back tick in JavaScript.

So we pass a format, and then look at the arguments. We pass a format as a string, and then Ellipsis any, ellipsis means any amount of arguments and any seems to be anything, so we'll see. So that means that first, we need a string. We can say, for example, the pointer is and the value is.

And I wanna put the pointer here and the value here, I wanna set placeholders. Printf works with percentage and a character. For example, if I'm expecting an integer, I can use i, if I'm expecting a string, s. If I don't know what I'm expecting or I don't care, in Go only, this is Go only, I can use v and that's value, so any value, just take the value from it.

I don't know what that is. And I can say then value and value, and then I need to pass two arguments, one per placeholder. So I can pass the pointerAge and *pointerAge. So I'm creating an output that will look better in the console. So if I execute this, it says the pointer is an address and the value is the value.

The problem is that it doesn't create a new line after, there is no printInf. So if you want a new line, you can use this character. You escape and new line, that's an new line character. That's for playing with the console actually, right? So printf will actually let us create the more complex output into the console.

Does that make sense? So in this case, we can see the pointerAge as we are receiving it, we see it's actually an address. It's a memory address, not really the value. And if we use a star as a prefix, we actually get it into the value.
>> Are there double pointers in the end?

>> Yeah, you can do double pointers, so you can get really crazy with that, so you can do two stars here. So in that case, you have a pointer that has a pointer to the value. So it's like you are proxying your data around the world. You have a memory address that is pointing to another memory address, and that one is pointing to the value.

Yeah, you can do that. There are some niche situation where that makes sense, if not, you don't get into that. But do you understand why do we need this? Because if not, we cannot modify the argument, we're modifying a copy, not the original one. Okay, it's just that.

That's all. We don't have any metrics over pointers as in C are things more complicated. So it's just that. If you got that, that's all.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now