WEBVTT 0 00:01.490 --> 00:03.390 Welcome! In this lecture, 1 00:03.380 --> 00:07.450 you're going to learn how to work with pointers to composite types. 2 00:07.490 --> 00:10.670 This will be an introductory lecture. In the upcoming lectures, 3 00:10.670 --> 00:12.920 you will see more examples (about pointers to composite types). 4 00:12.920 --> 00:14.200 All right let's get started. 5 00:17.140 --> 00:19.280 Let's start with arrays. 6 00:19.330 --> 00:26.290 Let me declare an array with a couple of numbers, and I'm going to increment them using a function. 7 00:26.310 --> 00:28.430 Let me also print the result. 8 00:28.470 --> 00:38.150 Now I'm going to declare the incr function, and I'm going to increment the numbers using a loop. 9 00:38.200 --> 00:41.640 It doesn't work, the numbers are the same. 10 00:41.740 --> 00:44.960 Remember arrays are bare values. 11 00:45.040 --> 00:50.570 So when you assign them or pass them to functions they get copied. 12 00:50.680 --> 00:57.940 I can prove this by printing the array's address. First, in here, and I'm going to print the incr function's 13 00:58.000 --> 01:02.780 array. As you can see, they have different addresses. 14 01:02.780 --> 01:05.930 So there are two different array values. 15 01:05.930 --> 01:09.380 That's why the incr function cannot change the original one. 16 01:10.100 --> 01:16.970 So, in this case, you may want to use a pointer instead. Let's duplicate the function. This time I'm going 17 01:16.970 --> 01:20.950 to use a pointer to the array. 18 01:21.050 --> 01:27.760 Now I'm going to run the function by giving it the address of the nums array. 19 01:27.790 --> 01:28.630 Now it works. 20 01:28.630 --> 01:37.930 The original numbers also change. The numbers were 1 2 and 3, but now they are 2 3 and 4. By the way, 21 01:37.930 --> 01:42.790 I don't need to use the indirection operator here because Go automatically use it. 22 01:42.790 --> 01:49.480 Let me show you that by getting the nums value from the pointer like so. It still works. 23 01:49.510 --> 01:49.870 Okay. 24 01:49.910 --> 01:52.090 Let me directly use the nums instead. 25 01:52.190 --> 01:53.480 It is clearer. 26 01:53.870 --> 01:56.480 Now let's talk about pointers to slices. 27 01:56.960 --> 01:59.060 Let me declare a slice of strings. 28 01:59.600 --> 02:03.090 Let's say you want to convert the strings to uppercase like. 29 02:03.110 --> 02:09.840 So for now I'm going to pass the slice value without a pointer like so. Let's print the result. 30 02:09.940 --> 02:15.540 Okay let's declare the up function. It takes a slice of strings and doesn't return value. 31 02:15.540 --> 02:24.630 Now, I'm going to convert the strings to uppercase in a loop like so. As you can see, the elements 32 02:24.630 --> 02:25.500 change. 33 02:25.500 --> 02:32.820 Remember, a slice already contains a pointer in its slice header, so you don't need to pass a pointer 34 02:32.880 --> 02:35.090 to a slice okay. 35 02:35.110 --> 02:42.050 What if you want to add a new element? The original slice doesn't see the change. 36 02:42.120 --> 02:43.230 Let's see why. 37 02:43.520 --> 02:47.000 First let me print the slice's address here. 38 02:47.120 --> 02:47.680 Right above, 39 02:47.760 --> 02:55.840 Let me print it here as well. As you can see there are two different addresses because there are two different 40 02:55.840 --> 02:57.330 slice headers. 41 02:57.370 --> 03:01.230 That's why the up function cannot change the original slice. 42 03:01.360 --> 03:05.140 It can only update its own local copy. 43 03:05.140 --> 03:11.590 Now let's pass the slice's address to a new function like so. I'm going to duplicate the up function 44 03:11.650 --> 03:13.960 and change everything to upPtr. 45 03:14.620 --> 03:18.520 Let's change the input to a pointer of a string slice. 46 03:18.670 --> 03:21.700 There are errors because the list is not a slice. 47 03:21.760 --> 03:24.280 It's a pointer to a slice. 48 03:24.280 --> 03:29.470 It was working with arrays because the Go language was helping us there. 49 03:29.470 --> 03:35.320 However, it doesn't help us here because slices are not meant to be used with a pointer. 50 03:35.320 --> 03:43.260 Then again, as an example, let's continue. Let's assign the slice value to a variable. So, lv becomes a 51 03:43.260 --> 03:44.550 string slice. 52 03:44.550 --> 03:46.790 Let's also change these. 53 03:46.830 --> 03:48.810 Now here is the interesting part. 54 03:48.810 --> 03:55.480 I'm going to append the original slice using the indirection like so. I'm also going to remove the address 55 03:55.480 --> 03:58.630 operator because the list is already a pointer. 56 03:58.720 --> 04:07.020 First, it will print the address of the list then it'll print the list's elements. As you can see it works. 57 04:07.040 --> 04:11.000 Let's take a look at the addresses. upPtr and slices functions 58 04:11.000 --> 04:12.840 look at the same address. 59 04:12.860 --> 04:18.080 That is why the upPtr function can update the slices function's slice header. 60 04:18.230 --> 04:22.540 As I said, passing slices to functions are not common. 61 04:22.640 --> 04:25.320 So please do not use pointers with slices. 62 04:25.710 --> 04:31.720 I have explained all of this because I want you to have a deeper understanding of pointers. 63 04:31.730 --> 04:36.190 Now let's talk about pointers to maps by declaring another function. 64 04:36.230 --> 04:38.640 Let me declare a confused map. 65 04:38.780 --> 04:43.680 It's a confused map because it maps 1 to 2, 2 to 1. 66 04:44.210 --> 04:47.900 Let's call a function that fixes the map. 67 04:47.990 --> 04:50.380 Let's print the result again. 68 04:50.390 --> 04:52.610 Let's declare the fix function. 69 04:52.610 --> 04:54.730 It just takes a map value. 70 04:54.830 --> 04:55.060 Okay. 71 04:55.070 --> 05:02.420 Let's assign the correct values to the map and let's add one more key. As you can see, the maps function 72 05:02.540 --> 05:05.470 also sees the change. Like a slice, 73 05:05.480 --> 05:08.540 you don't need to pass a pointer to a map. 74 05:08.540 --> 05:09.650 Remember a map 75 05:09.650 --> 05:12.640 value is already a pointer. 76 05:12.650 --> 05:17.640 Now let's talk about pointers to structs by declaring another function. 77 05:17.690 --> 05:20.690 I'm going to create a new struct type at the package level. 78 05:20.690 --> 05:25.370 It has two fields: name and rooms. 79 05:25.370 --> 05:31.870 Let's create the house value. Let's call a function to add one more room. 80 05:31.940 --> 05:33.990 Let's also print the result. 81 05:34.070 --> 05:36.920 Now let's declare the addRoom function. 82 05:37.040 --> 05:46.120 It takes a house value. Inside, I'm going to increment the room count. The original struct stays the same. 83 05:46.230 --> 05:48.980 The room count is still 5. 84 05:49.030 --> 05:49.960 Let's investigate 85 05:49.990 --> 05:50.830 why is that so. 86 05:51.220 --> 05:52.510 Let's investigate it also. 87 05:52.640 --> 05:57.450 In the addRoom function, there are two struct values. 88 05:57.450 --> 06:00.680 That's why the original struct doesn't change. 89 06:00.870 --> 06:04.740 Let's duplicate the addRoom function and use a pointer. Let 90 06:04.760 --> 06:07.880 me also remove the address operator from here. 91 06:07.920 --> 06:13.890 Now let's call the function from the structs function above by passing it a pointer to the myHouse 92 06:13.890 --> 06:15.850 value. 93 06:16.070 --> 06:18.920 It works, the room count becomes 6. 94 06:18.920 --> 06:24.710 Now let's take a look at the addresses. As you can see, addRoomPtr points to the original struct value. 95 06:24.710 --> 06:27.650 That is why it can update the original struct value. 96 06:27.650 --> 06:33.990 By the way, did you notice that I have used the pointer value directly without an indirection operator. 97 06:34.040 --> 06:41.270 I mean, I didn't use it like so, it's because Go helps us here as well, it automatically does this behind the 98 06:41.270 --> 06:43.030 scenes so we don't need to. 99 06:43.160 --> 06:48.390 By the way, you can take addresses of the individual struct fields go also helps us. 100 06:48.410 --> 06:49.970 Now we want to do that. 101 06:50.030 --> 06:54.340 Let me show you the address of the name field. 102 06:54.420 --> 06:57.000 Let me also show you the rooms field. 103 06:58.240 --> 07:01.400 As you can see, each field has a different address. 104 07:01.400 --> 07:08.630 However, note that they are contiguous. On my machine, a string value is 16 bytes, and an int value 105 07:08.660 --> 07:09.980 is 8 bytes. 106 07:10.040 --> 07:14.470 So after the string value, the int value immediately follows. 107 07:14.510 --> 07:22.650 This makes struct values efficient because the CPU can cache them easily. However, you cannot find the address 108 07:22.680 --> 07:28.230 of a map element. It's because, behind the scenes, the Go runtime can change a map 109 07:28.230 --> 07:34.650 element's address. However, you can also find the address of individual slice elements. 110 07:37.350 --> 07:43.190 As you can see like arrays and structs, slice elements are also contiguous. Here, 111 07:43.200 --> 07:45.500 Each one is 16 bytes (not 8, sorry). 112 07:45.570 --> 07:47.870 Let's try it with the arrays. 113 07:47.910 --> 07:50.480 Now I'm going to print the current element's address like so. 114 07:53.740 --> 07:54.230 Again, 115 07:54.250 --> 08:00.510 the array elements are contiguous. Alright! That'ss all for now. See in the next lecture. Bye!