Welcome! In this lecture,
you're going to learn how to work with pointers to composite types.
This will be an introductory lecture. In the upcoming lectures,
you will see more examples (about pointers to composite types).
All right let's get started.
Let's start with arrays.
Let me declare an array with a couple of numbers, and I'm going to increment them using a function.
Let me also print the result.
Now I'm going to declare the incr function, and I'm going to increment the numbers using a loop.
It doesn't work, the numbers are the same.
Remember arrays are bare values.
So when you assign them or pass them to functions they get copied.
I can prove this by printing the array's address. First, in here, and I'm going to print the incr function's
array. As you can see, they have different addresses.
So there are two different array values.
That's why the incr function cannot change the original one.
So, in this case, you may want to use a pointer instead. Let's duplicate the function. This time I'm going
to use a pointer to the array.
Now I'm going to run the function by giving it the address of the nums array.
Now it works.
The original numbers also change. The numbers were 1 2 and 3, but now they are 2 3 and 4. By the way,
I don't need to use the indirection operator here because Go automatically use it.
Let me show you that by getting the nums value from the pointer like so. It still works.
Okay.
Let me directly use the nums instead.
It is clearer.
Now let's talk about pointers to slices.
Let me declare a slice of strings.
Let's say you want to convert the strings to uppercase like.
So for now I'm going to pass the slice value without a pointer like so. Let's print the result.
Okay let's declare the up function. It takes a slice of strings and doesn't return value.
Now, I'm going to convert the strings to uppercase in a loop like so. As you can see, the elements
change.
Remember, a slice already contains a pointer in its slice header, so you don't need to pass a pointer
to a slice okay.
What if you want to add a new element? The original slice doesn't see the change.
Let's see why.
First let me print the slice's address here.
Right above,
Let me print it here as well. As you can see there are two different addresses because there are two different
slice headers.
That's why the up function cannot change the original slice.
It can only update its own local copy.
Now let's pass the slice's address to a new function like so. I'm going to duplicate the up function
and change everything to upPtr.
Let's change the input to a pointer of a string slice.
There are errors because the list is not a slice.
It's a pointer to a slice.
It was working with arrays because the Go language was helping us there.
However, it doesn't help us here because slices are not meant to be used with a pointer.
Then again, as an example, let's continue. Let's assign the slice value to a variable. So, lv becomes a
string slice.
Let's also change these.
Now here is the interesting part.
I'm going to append the original slice using the indirection like so. I'm also going to remove the address
operator because the list is already a pointer.
First, it will print the address of the list then it'll print the list's elements. As you can see it works.
Let's take a look at the addresses. upPtr and slices functions
look at the same address.
That is why the upPtr function can update the slices function's slice header.
As I said, passing slices to functions are not common.
So please do not use pointers with slices.
I have explained all of this because I want you to have a deeper understanding of pointers.
Now let's talk about pointers to maps by declaring another function.
Let me declare a confused map.
It's a confused map because it maps 1 to 2, 2 to 1.
Let's call a function that fixes the map.
Let's print the result again.
Let's declare the fix function.
It just takes a map value.
Okay.
Let's assign the correct values to the map and let's add one more key. As you can see, the maps function
also sees the change. Like a slice,
you don't need to pass a pointer to a map.
Remember a map
value is already a pointer.
Now let's talk about pointers to structs by declaring another function.
I'm going to create a new struct type at the package level.
It has two fields: name and rooms.
Let's create the house value. Let's call a function to add one more room.
Let's also print the result.
Now let's declare the addRoom function.
It takes a house value. Inside, I'm going to increment the room count. The original struct stays the same.
The room count is still 5.
Let's investigate
why is that so.
Let's investigate it also.
In the addRoom function, there are two struct values.
That's why the original struct doesn't change.
Let's duplicate the addRoom function and use a pointer. Let
me also remove the address operator from here.
Now let's call the function from the structs function above by passing it a pointer to the myHouse
value.
It works, the room count becomes 6.
Now let's take a look at the addresses. As you can see, addRoomPtr points to the original struct value.
That is why it can update the original struct value.
By the way, did you notice that I have used the pointer value directly without an indirection operator.
I mean, I didn't use it like so, it's because Go helps us here as well, it automatically does this behind the
scenes so we don't need to.
By the way, you can take addresses of the individual struct fields go also helps us.
Now we want to do that.
Let me show you the address of the name field.
Let me also show you the rooms field.
As you can see, each field has a different address.
However, note that they are contiguous. On my machine, a string value is 16 bytes, and an int value
is 8 bytes.
So after the string value, the int value immediately follows.
This makes struct values efficient because the CPU can cache them easily. However, you cannot find the address
of a map element. It's because, behind the scenes, the Go runtime can change a map
element's address. However, you can also find the address of individual slice elements.
As you can see like arrays and structs, slice elements are also contiguous. Here,
Each one is 16 bytes (not 8, sorry).
Let's try it with the arrays.
Now I'm going to print the current element's address like so.
Again,
the array elements are contiguous. Alright! That'ss all for now. See in the next lecture. Bye!