WEBVTT 0 00:01.380 --> 00:02.130 Welcome back. 1 00:02.790 --> 00:06.980 Lastly you refactored the log parser to functions. 2 00:06.990 --> 00:09.260 Now it's time to rewrite it once more 3 00:09.270 --> 00:13.110 using pointers. OK, let's take a look at the code. 4 00:17.410 --> 00:25.030 newParser returns a new parser struct value. The parse function passes a line from the log file and 5 00:25.030 --> 00:27.300 returns the parsing result. 6 00:27.310 --> 00:32.260 Lastly, the update function updates the parser and returns a new copy. 7 00:32.320 --> 00:36.120 So the main function can update its copy. 8 00:36.190 --> 00:43.090 Let's take a look at the update function now. Here, if it wasn't returning a new parser, the main function 9 00:43.240 --> 00:46.790 wouldn't see the changes to the sum and total fields. 10 00:47.530 --> 00:52.840 However, if you use a pointer, you don't need to return a new parser value. 11 00:52.840 --> 00:56.060 So let's remove the return statement from here. 12 00:56.130 --> 01:02.780 Let's also remove the result value. Let's change the input value to a pointer instead. 13 01:02.780 --> 01:05.600 I don't need to change anything else here. 14 01:05.600 --> 01:07.540 Let's go to the main function. 15 01:07.880 --> 01:13.690 Let's remove the assignment from here. It expects a pointer. 16 01:13.720 --> 01:16.750 So, let's take the p variable's address. 17 01:16.750 --> 01:21.330 So this sends the memory address of the P variable to the update function. 18 01:22.680 --> 01:23.340 Voila! 19 01:23.340 --> 01:24.370 It still works. 20 01:24.390 --> 01:30.460 It's because, the update function can now update the original parser value through the pointer. 21 01:30.660 --> 01:35.060 So the update function doesn't need to return a new parser value. 22 01:35.190 --> 01:36.360 It can directly the update 23 01:36.360 --> 01:38.520 the main function's parser value 24 01:38.520 --> 01:42.210 now. Let's investigate how it works. 25 01:42.200 --> 01:50.010 First I'm going to print the address of the original parser. 26 01:50.090 --> 01:52.670 Let's go into the parser file. Here, 27 01:52.700 --> 01:54.620 I'm going to print the address of the copy. 28 01:57.770 --> 02:02.850 P is a pointer, so I don't need to take its address. So I can directly print it. 29 02:02.990 --> 02:07.040 Let me also print the address of the P variable. 30 02:07.070 --> 02:09.640 This is the address of the main function's parser. 31 02:09.710 --> 02:16.340 It is the original parser. The update function receives a pointer from the main function, and that pointer 32 02:16.370 --> 02:19.810 points to the memory address of the original parser value. 33 02:19.820 --> 02:26.450 Here you can see that, they all point to the same parser value. Although each one of them points to the 34 02:26.450 --> 02:28.560 main function's parser value, 35 02:28.640 --> 02:36.540 they have different addresses. It's because each one is a different pointer variable. OK! Let me remove 36 02:36.570 --> 02:45.490 these print calls. By the way, I think updating the parsed lines is the responsibility of the parse function. 37 02:45.590 --> 02:49.120 It's because, it is the one who handles the parsing. 38 02:49.120 --> 02:59.140 So now, let's move that responsibility to the parse function. Let's try it with an incorrect log file. It 39 02:59.140 --> 03:07.180 reports an incorrect line now because the pass function creates a new of value. It's because it receives 40 03:07.270 --> 03:14.290 a parser value, so it copies the parser value. Then it increments the field inside the parser value 41 03:14.290 --> 03:14.770 here. 42 03:14.770 --> 03:19.420 So the lines field always starts at zero, then it becomes one. 43 03:19.420 --> 03:26.800 So this function can never update the main function's parser value. It has its own parser value. 44 03:26.800 --> 03:30.450 So instead, let's get a pointer to the original parser value. 45 03:31.180 --> 03:34.460 Let's go back to the main function here. 46 03:34.470 --> 03:36.060 I need to pass a pointer 47 03:38.640 --> 03:39.350 Cool! 48 03:39.450 --> 03:40.440 Now it works! 49 03:40.470 --> 03:47.160 Now the parse function can update the main function's parser value through the pointer. So it updates 50 03:47.160 --> 03:48.480 the lines field as well. 51 03:49.200 --> 03:51.020 Let's go to the main function. 52 03:51.050 --> 03:57.740 Here's a question: What happens if you pass a new value instead? 53 03:57.790 --> 04:00.520 It says there is a problem on this line. 54 04:00.610 --> 04:01.900 Let's go there. 55 04:01.900 --> 04:07.740 The error message says that this code de-references (indirects) using a nil pointer. Here, 56 04:07.810 --> 04:12.880 it tries to get the value but the pointer doesn't point to a memory address. 57 04:12.910 --> 04:14.820 So there is nothing to return. 58 04:14.890 --> 04:18.270 That is why it panics and terminates the program. 59 04:18.370 --> 04:24.170 So you should be careful while using pointers. Nil pointers can crash your program. 60 04:24.520 --> 04:28.970 Okay let me fix it. OK, so far so good. 61 04:29.360 --> 04:30.890 So what's next? 62 04:30.890 --> 04:32.800 Let's take a look at the main function again. 63 04:32.810 --> 04:35.030 There are two responsibilities here. 64 04:35.030 --> 04:39.380 First, it parses the log file and updates the parser. 65 04:39.380 --> 04:42.150 Second, it summarizes the results. 66 04:42.170 --> 04:47.780 So instead of summarizing the result in the main function, I'm going to create another function to do 67 04:47.780 --> 04:48.080 that 68 04:48.080 --> 04:54.830 like so. It takes a parser value, and I'm going to cut the code from the main function, and I'm going to 69 04:54.830 --> 04:57.380 move it into the summarize function. 70 04:57.380 --> 05:01.350 I also need to call it like so. It works, 71 05:01.400 --> 05:01.670 good. 72 05:02.390 --> 05:07.400 So why did I use a value to the parser instead of a pointer? 73 05:07.460 --> 05:12.840 It's because, the summarize function doesn't need to change it but only prints it. 74 05:12.910 --> 05:13.560 Okay. 75 05:13.760 --> 05:16.350 In the structs section there was a problem. 76 05:16.400 --> 05:17.950 Let's remember it. 77 05:18.020 --> 05:24.980 I was trying to increase the visits per domain like so. But it wasn't working because map elements are 78 05:24.980 --> 05:26.540 not addressable. 79 05:26.630 --> 05:28.900 So what is addressability? 80 05:28.940 --> 05:31.610 Let me explain it through an example. 81 05:31.610 --> 05:35.690 For example, I cannot access the memory address of a map element. 82 05:35.690 --> 05:39.650 It says you cannot access the memory address of the map element. 83 05:39.680 --> 05:43.490 So this means a map element is not an addressable value. 84 05:43.490 --> 05:52.410 However, you can copy the map element. Then you can take its address. When you do so, it becomes an addressable 85 05:52.410 --> 05:53.490 value. 86 05:53.760 --> 05:59.610 You can take the address of the clone variable because it's a copy of the original map element. It is 87 05:59.610 --> 06:01.530 not the original map element. 88 06:01.530 --> 06:07.310 So in summary, if you can take an address of a value, then it is an addressable value. 89 06:07.680 --> 06:10.390 Otherwise it is not an addressable value. 90 06:10.440 --> 06:14.450 As I've said map elements are not addressable values. 91 06:14.460 --> 06:19.520 It's because, sometimes Go runtime moves them on the memory without asking you. 92 06:19.680 --> 06:24.750 Because of that Go doesn't allow you to take the address of the map elements. 93 06:24.750 --> 06:31.530 That's why when you get an element from a map, it only returns you a copy, so that you never will be able 94 06:31.530 --> 06:34.540 to access to the original map element. 95 06:34.560 --> 06:35.270 All right. 96 06:35.290 --> 06:36.870 That's all for now. See you in the next lecture.