1 00:00:06,656 --> 00:00:09,430 - I wanna show you another piece of code here 2 00:00:09,430 --> 00:00:12,050 around the idea of side effects and how dangerous 3 00:00:12,050 --> 00:00:14,460 they can become if you're not aware of it. 4 00:00:14,460 --> 00:00:15,610 And this is all I'm trying to do, 5 00:00:15,610 --> 00:00:17,500 I'm not trying to scare you away from the data structure, 6 00:00:17,500 --> 00:00:19,380 I'm not trying to make you go and have to use 7 00:00:19,380 --> 00:00:21,040 the built in function, copy, all the time. 8 00:00:21,040 --> 00:00:22,650 That's not it at all. 9 00:00:22,650 --> 00:00:24,240 I just wanna continue to iterate 10 00:00:24,240 --> 00:00:26,020 that when you're using pointer semantics, 11 00:00:26,020 --> 00:00:27,930 and we're mutating memory, 12 00:00:27,930 --> 00:00:29,650 we have to be aware of the side effects. 13 00:00:29,650 --> 00:00:31,850 This is what makes programming difficult. 14 00:00:31,850 --> 00:00:34,020 Your functional programming language friends 15 00:00:34,020 --> 00:00:35,270 don't have to worry about this stuff. 16 00:00:35,270 --> 00:00:38,140 Functional programming says everything is value semantics, 17 00:00:38,140 --> 00:00:40,000 every piece of code, every function we call, 18 00:00:40,000 --> 00:00:42,060 operates on its own piece of data, 19 00:00:42,060 --> 00:00:44,290 but we don't get all the efficiencies we need 20 00:00:44,290 --> 00:00:47,020 to have the fastest programs that we want, 21 00:00:47,020 --> 00:00:49,570 and this is why GO is brilliant in giving you 22 00:00:49,570 --> 00:00:52,260 the responsibility of both value and pointer semantics, 23 00:00:52,260 --> 00:00:54,590 but we have to be aware of when we're using what, 24 00:00:54,590 --> 00:00:56,090 and when we're using the pointer semantics, 25 00:00:56,090 --> 00:00:57,660 we have to be aware of the mutations 26 00:00:57,660 --> 00:00:59,620 and the problems they can cause. 27 00:00:59,620 --> 00:01:03,600 So, let's take a look at this program here. 28 00:01:03,600 --> 00:01:05,900 We've got a user defined type called user, 29 00:01:05,900 --> 00:01:08,630 and the idea is that I have a system of users, 30 00:01:08,630 --> 00:01:11,280 and we're gonna track likes for this user. 31 00:01:11,280 --> 00:01:13,060 We're gonna track likes throughout the app. 32 00:01:13,060 --> 00:01:15,140 Now let's just say I have a small system, 33 00:01:15,140 --> 00:01:17,940 and we start this system up, it starts running, 34 00:01:17,940 --> 00:01:20,150 and we only have three users. 35 00:01:20,150 --> 00:01:22,670 So, I go ahead right here, in this program, 36 00:01:22,670 --> 00:01:26,140 and I create my slice, here it is, my slice, 37 00:01:26,140 --> 00:01:28,210 of three users, there they are. 38 00:01:28,210 --> 00:01:31,280 Now, this is set to its zero value. 39 00:01:31,280 --> 00:01:32,670 It's a slice of users, so I don't know why 40 00:01:32,670 --> 00:01:35,100 I'm writing strings here, funny stuff, Bill. 41 00:01:35,100 --> 00:01:37,150 But we're just gonna maintain our likes here, 42 00:01:37,150 --> 00:01:38,040 and we know right now 43 00:01:38,040 --> 00:01:40,790 that these users start with zero likes, 44 00:01:40,790 --> 00:01:43,360 and let's just pretend we're gonna use the index position 45 00:01:43,360 --> 00:01:45,310 and bind it to a user value. 46 00:01:45,310 --> 00:01:48,720 So there we are, we've got users zero, one, and two. 47 00:01:48,720 --> 00:01:50,420 They're like are set right there. 48 00:01:50,420 --> 00:01:52,600 We've got a length and capacity of three. 49 00:01:52,600 --> 00:01:55,410 Now, I go ahead like I would normally do in a program, 50 00:01:55,410 --> 00:01:58,310 and I wanna share the user one, right here, 51 00:01:58,310 --> 00:02:00,950 I wanna share it, and I create some sort of pointer 52 00:02:00,950 --> 00:02:02,870 that now points to user one. 53 00:02:02,870 --> 00:02:04,850 It's very possible that I'm gonna do this, 54 00:02:04,850 --> 00:02:07,780 and I wanna share that user down the call stack, 55 00:02:07,780 --> 00:02:09,570 in some other part of my program 56 00:02:09,570 --> 00:02:11,650 that's handling likes on some event, 57 00:02:11,650 --> 00:02:13,690 so we can continue to increment this, 58 00:02:13,690 --> 00:02:16,400 and in fact, on line 23, what you see 59 00:02:16,400 --> 00:02:19,880 is through the use of the share user pointer, 60 00:02:19,880 --> 00:02:23,060 we increment the value that the pointer points to. 61 00:02:23,060 --> 00:02:27,330 After line 23, this user doesn't have zero likes, 62 00:02:27,330 --> 00:02:28,970 they have one. 63 00:02:28,970 --> 00:02:31,240 Brilliant, but guess what happens? 64 00:02:31,240 --> 00:02:33,290 If you notice here on line 26, 65 00:02:33,290 --> 00:02:35,910 and I'll add some extra print statements here 66 00:02:35,910 --> 00:02:39,690 so we can isolate the output on the screen, 67 00:02:39,690 --> 00:02:44,270 we should see that that user one has one like 68 00:02:44,270 --> 00:02:46,400 and the others have zero. 69 00:02:46,400 --> 00:02:48,760 And there it is, user zero, no likes, 70 00:02:48,760 --> 00:02:51,980 user one, one like, user two, zero likes. 71 00:02:51,980 --> 00:02:54,310 Brilliant, it's exactly what I wanted to see. 72 00:02:54,310 --> 00:02:57,100 Now, the system is running, it's dynamic, 73 00:02:57,100 --> 00:03:00,590 some user now registers on the system, 74 00:03:00,590 --> 00:03:03,880 and we go ahead and do what I would expect us to do, 75 00:03:03,880 --> 00:03:05,630 we append a user, 76 00:03:05,630 --> 00:03:08,360 but watch what happens on the append. 77 00:03:08,360 --> 00:03:10,110 Is length and capacity the same? 78 00:03:10,110 --> 00:03:12,410 The answer is yes, it is. 79 00:03:12,410 --> 00:03:14,040 Uh oh, what does that mean? 80 00:03:14,040 --> 00:03:15,930 It means that we're now going to have to create 81 00:03:15,930 --> 00:03:17,770 a new backing array. 82 00:03:17,770 --> 00:03:21,030 Well, our new backing array will be doubling in size, 83 00:03:21,030 --> 00:03:24,040 and our length and capacities are going to change. 84 00:03:24,040 --> 00:03:26,490 Suddenly, we're gonna have a length of four, 85 00:03:26,490 --> 00:03:29,270 but a capacity of six, which also means that 86 00:03:29,270 --> 00:03:32,800 all of this data is going to have to be copied, 87 00:03:32,800 --> 00:03:34,653 and it will, here we are, 88 00:03:35,770 --> 00:03:39,420 and we now point to this. 89 00:03:39,420 --> 00:03:41,680 Notice what has just happened. 90 00:03:41,680 --> 00:03:45,440 This pointer that was pointing to this backing array 91 00:03:45,440 --> 00:03:47,540 is still pointing to this backing array, 92 00:03:47,540 --> 00:03:51,520 but this is no longer our data. 93 00:03:51,520 --> 00:03:54,530 This is now our data, because of the append. 94 00:03:54,530 --> 00:03:56,560 Which means that if I continue 95 00:03:56,560 --> 00:03:59,580 to increment likes for the user, 96 00:03:59,580 --> 00:04:03,790 like you see on line 34, guess what? 97 00:04:03,790 --> 00:04:06,490 They don't get registered. 98 00:04:06,490 --> 00:04:09,040 You might think, Bill, this would never happen, 99 00:04:09,040 --> 00:04:10,390 this would never happen. 100 00:04:10,390 --> 00:04:13,740 We're incrementing this, we're not incrementing this, 101 00:04:13,740 --> 00:04:16,090 but this is the data that we're working with now, 102 00:04:16,090 --> 00:04:17,000 and guess what? 103 00:04:17,000 --> 00:04:18,390 We kinda have a memory leak 104 00:04:18,390 --> 00:04:21,100 in a sense that this memory can't get released 105 00:04:21,100 --> 00:04:23,150 because of this pointer right here. 106 00:04:23,150 --> 00:04:25,310 And you might think, Bill, this would never happen, 107 00:04:25,310 --> 00:04:28,220 and I know some of the best GO developers on the planet 108 00:04:28,220 --> 00:04:32,460 who have created bugs like this, not thinking how append, 109 00:04:32,460 --> 00:04:34,400 when length and capacity are the same, 110 00:04:34,400 --> 00:04:37,700 is going to make a copy of the current data, 111 00:04:37,700 --> 00:04:39,160 which is the point of truth, 112 00:04:39,160 --> 00:04:41,050 and now make this the point of truth, 113 00:04:41,050 --> 00:04:43,200 and yet we have these pointers now 114 00:04:43,200 --> 00:04:45,710 working against the old data structures. 115 00:04:45,710 --> 00:04:46,881 This is a side effect, 116 00:04:46,881 --> 00:04:51,480 these are the nasty bugs that are so hard to find, 117 00:04:51,480 --> 00:04:53,530 and so anytime we're working with pointer semantics, 118 00:04:53,530 --> 00:04:56,950 that's great, it's gonna give us levels of efficiency, 119 00:04:56,950 --> 00:04:59,060 right, we have to be careful there, 120 00:04:59,060 --> 00:05:00,840 but we also have to make sure 121 00:05:00,840 --> 00:05:05,304 that we're very clean with data updates, like with slices, 122 00:05:05,304 --> 00:05:07,770 and that our mutations are not going to cause problems, 123 00:05:07,770 --> 00:05:10,670 or the mutations are happening in the wrong place. 124 00:05:10,670 --> 00:05:13,350 This is just a program to show you 125 00:05:13,350 --> 00:05:15,180 what a side effect really can look like 126 00:05:15,180 --> 00:05:18,300 in production-level code, and how careful we have to be 127 00:05:18,300 --> 00:05:21,520 when we're sharing these slices beyond program boundaries, 128 00:05:21,520 --> 00:05:24,180 especially if the call to append is going to happen. 129 00:05:24,180 --> 00:05:26,250 And one of the things I do a lot 130 00:05:26,250 --> 00:05:28,800 is any time I see a call to append in code, 131 00:05:28,800 --> 00:05:32,020 I immediately put the breaks on the code review, 132 00:05:32,020 --> 00:05:34,680 because append can create some of the nastiest side effects 133 00:05:34,680 --> 00:05:35,690 you've ever seen. 134 00:05:35,690 --> 00:05:38,770 So unless the code is decoding or unmarshalling, 135 00:05:38,770 --> 00:05:41,650 usually an append call is somewhat of a smell, 136 00:05:41,650 --> 00:05:43,280 and it's not necessarily wrong, 137 00:05:43,280 --> 00:05:45,940 but we're gonna have to double and triple check 138 00:05:45,940 --> 00:05:48,360 that we're not causing some sort of side effect 139 00:05:48,360 --> 00:05:51,003 with a backing array that's gonna get replaced.