1 00:00:06,600 --> 00:00:09,380 - So we just looked at our value semantic example, 2 00:00:09,380 --> 00:00:11,910 but let's imagine that what we really wanted 3 00:00:11,910 --> 00:00:14,080 is not the goroutine here operating 4 00:00:14,080 --> 00:00:16,100 in its own sandbox and its own copy. 5 00:00:16,100 --> 00:00:18,200 Let's say what that next data transformation, 6 00:00:18,200 --> 00:00:19,790 what it really needed to do, 7 00:00:19,790 --> 00:00:22,230 was manipulate the memory here, 8 00:00:22,230 --> 00:00:24,380 which was gonna be in the frame above us. 9 00:00:24,380 --> 00:00:26,850 Now what we need is pointer semantics, 10 00:00:26,850 --> 00:00:28,900 and pointer semantics serve one purpose 11 00:00:28,900 --> 00:00:31,360 and that is to share our piece of data 12 00:00:31,360 --> 00:00:33,330 across a program boundary. 13 00:00:33,330 --> 00:00:35,790 Sharing, if you don't need to share something, 14 00:00:35,790 --> 00:00:36,970 then you don't need a pointer, 15 00:00:36,970 --> 00:00:38,420 you don't need the pointer semantics, 16 00:00:38,420 --> 00:00:41,200 and this is where the pointers are really going to come in. 17 00:00:41,200 --> 00:00:43,610 Let's take a look at the mechanics around sharing 18 00:00:43,610 --> 00:00:45,890 and then continue to talk about the benefits 19 00:00:45,890 --> 00:00:47,770 and the costs of pointer semantics, 20 00:00:47,770 --> 00:00:48,880 and we'll try to continue 21 00:00:48,880 --> 00:00:51,800 to bring all this stuff together as we go. 22 00:00:51,800 --> 00:00:55,090 So let's go back to our original program. 23 00:00:55,090 --> 00:00:56,320 Let's come back here again. 24 00:00:56,320 --> 00:00:58,363 We're gonna clear our stack right here, 25 00:00:59,460 --> 00:01:02,010 here we are, and we've got our stack 26 00:01:02,010 --> 00:01:03,740 and we're operating in main. 27 00:01:03,740 --> 00:01:05,830 And main has its variable count, 28 00:01:05,830 --> 00:01:07,590 and we can get the value of count, 29 00:01:07,590 --> 00:01:09,710 we can get the address of count. 30 00:01:09,710 --> 00:01:12,980 But this time on line 17 we've done something different. 31 00:01:12,980 --> 00:01:15,710 I'm not passing the value of count 32 00:01:15,710 --> 00:01:17,790 across my program boundary. 33 00:01:17,790 --> 00:01:19,900 I want you to notice that what we're passing 34 00:01:19,900 --> 00:01:22,410 is the address of count. 35 00:01:22,410 --> 00:01:24,470 Now you might think that this is what's called 36 00:01:24,470 --> 00:01:25,690 a pass by reference. 37 00:01:25,690 --> 00:01:29,030 Lots of people say that this is a pass by reference. 38 00:01:29,030 --> 00:01:29,980 It really isn't. 39 00:01:29,980 --> 00:01:32,210 Remember pass by value means WYSIWYG. 40 00:01:32,210 --> 00:01:33,950 What you see is what you get. 41 00:01:33,950 --> 00:01:37,250 Pass by value means that we're making copies of data 42 00:01:37,250 --> 00:01:39,970 as we cross over program boundaries. 43 00:01:39,970 --> 00:01:42,230 This is a pass by value. 44 00:01:42,230 --> 00:01:45,970 It just so happens that the data we are copying and passing 45 00:01:45,970 --> 00:01:48,920 is not a value, it's an address. 46 00:01:48,920 --> 00:01:52,720 And I need to stress again that addresses are data. 47 00:01:52,720 --> 00:01:55,770 So since we're gonna make a copy of count's address, 48 00:01:55,770 --> 00:01:58,040 and pass that across the program boundary, 49 00:01:58,040 --> 00:02:00,180 we need to store an address. 50 00:02:00,180 --> 00:02:01,013 Guess what? 51 00:02:01,013 --> 00:02:03,200 This is what pointer variables are for. 52 00:02:03,200 --> 00:02:05,550 Pointer variables are not special. 53 00:02:05,550 --> 00:02:07,610 They aren't, they serve one purpose, 54 00:02:07,610 --> 00:02:10,620 and that is to store addresses. 55 00:02:10,620 --> 00:02:12,630 Our address data. 56 00:02:12,630 --> 00:02:15,360 Now if you look at the declaration 57 00:02:15,360 --> 00:02:17,910 of the parameters for increment, 58 00:02:17,910 --> 00:02:21,580 you can see now that we've added this operator called star. 59 00:02:21,580 --> 00:02:24,760 And the star operator is allowing now 60 00:02:24,760 --> 00:02:27,080 us to declare the pointer variable. 61 00:02:27,080 --> 00:02:28,430 I want you to understand that pointers 62 00:02:28,430 --> 00:02:30,040 are literal types. 63 00:02:30,040 --> 00:02:31,960 Remember when I said before in the other section 64 00:02:31,960 --> 00:02:35,950 we have name types, we have literal types, unnamed types. 65 00:02:35,950 --> 00:02:37,780 And pointers are literal types. 66 00:02:37,780 --> 00:02:41,250 You can take any existing type, like name type int, 67 00:02:41,250 --> 00:02:42,650 put the star in front of it, 68 00:02:42,650 --> 00:02:44,480 and you've just now identified 69 00:02:44,480 --> 00:02:47,100 the literal pointer type for that. 70 00:02:47,100 --> 00:02:49,780 And what that means it's changing everything, 71 00:02:49,780 --> 00:02:52,610 inc is no longer representing an integer, 72 00:02:52,610 --> 00:02:54,860 inc is now representing the ability 73 00:02:54,860 --> 00:02:58,050 to store an address. 74 00:02:58,050 --> 00:02:59,720 That's what we're going to be doing. 75 00:02:59,720 --> 00:03:02,430 And that address is going to point to something. 76 00:03:02,430 --> 00:03:03,820 In this case, what we've done is we've 77 00:03:03,820 --> 00:03:05,980 taken the address of count, 78 00:03:05,980 --> 00:03:09,350 and we've passed that across the program boundary. 79 00:03:09,350 --> 00:03:11,400 Which means that is what we're gonna be storing 80 00:03:11,400 --> 00:03:13,340 in this box, that address. 81 00:03:13,340 --> 00:03:16,560 Which now means that we're able to point to a piece of data 82 00:03:16,560 --> 00:03:19,100 outside of our frame. 83 00:03:19,100 --> 00:03:21,140 Pointers are for sharing. 84 00:03:21,140 --> 00:03:23,720 Pointers are confusing because of that star. 85 00:03:23,720 --> 00:03:27,080 The star dictates that this is now a pointer variable, 86 00:03:27,080 --> 00:03:29,250 it's always four to eight bytes of memory, 87 00:03:29,250 --> 00:03:31,820 depending upon the architecture, the size of an address, 88 00:03:31,820 --> 00:03:33,890 and that is what we're storing. 89 00:03:33,890 --> 00:03:35,880 But, this is very important. 90 00:03:35,880 --> 00:03:37,340 You might think, well Bill, 91 00:03:37,340 --> 00:03:40,300 If the star is what's dictating the variable's type, 92 00:03:40,300 --> 00:03:42,770 which it is, why can't we just say star? 93 00:03:42,770 --> 00:03:44,470 I mean it's the star that's dictating 94 00:03:44,470 --> 00:03:46,280 this is a four-eight by value. 95 00:03:46,280 --> 00:03:48,790 It's the star that's dictating this is a pointer variable 96 00:03:48,790 --> 00:03:50,130 and what's gonna be stored. 97 00:03:50,130 --> 00:03:53,340 You're right, except for one thing, it's not enough 98 00:03:53,340 --> 00:03:54,760 to just store the address. 99 00:03:54,760 --> 00:03:56,980 The whole reason for storing the address 100 00:03:56,980 --> 00:03:59,250 is because we want to manipulate, 101 00:03:59,250 --> 00:04:01,150 read and/or write the memory, 102 00:04:01,150 --> 00:04:03,600 that that address is locating us to. 103 00:04:03,600 --> 00:04:04,900 In this case, this count. 104 00:04:04,900 --> 00:04:07,740 And I told you before, you cannot read and write to memory 105 00:04:07,740 --> 00:04:09,610 unless you understand the memory's type. 106 00:04:09,610 --> 00:04:11,580 You must understand the size 107 00:04:11,580 --> 00:04:13,580 and the representation of this memory. 108 00:04:13,580 --> 00:04:16,140 Type is life. 109 00:04:16,140 --> 00:04:20,830 So, we can't just say star, you've gotta say star int. 110 00:04:20,830 --> 00:04:22,760 What I'm saying is I want an address. 111 00:04:22,760 --> 00:04:25,210 Absolutely, no pause, I need an address. 112 00:04:25,210 --> 00:04:26,353 But guess what? 113 00:04:26,353 --> 00:04:27,650 It can't just be any address, 114 00:04:27,650 --> 00:04:30,370 it has to be and address to an integer, 115 00:04:30,370 --> 00:04:32,940 because I wanna read and write integers. 116 00:04:32,940 --> 00:04:34,830 And we're gonna get that type safetiness, 117 00:04:34,830 --> 00:04:36,810 the compiler won't let me pass any address, 118 00:04:36,810 --> 00:04:41,220 only addresses to values that are based on the integer type. 119 00:04:41,220 --> 00:04:42,053 There we are. 120 00:04:42,053 --> 00:04:44,150 And then what you see on line 28 121 00:04:44,150 --> 00:04:47,650 is the use of the star operator again. 122 00:04:47,650 --> 00:04:49,080 This can be confusing. 123 00:04:49,080 --> 00:04:51,660 Remember the star is being used during type decoration, 124 00:04:51,660 --> 00:04:53,520 now it's being using to say one thing. 125 00:04:53,520 --> 00:04:55,380 Remember we're gonna put everything in English. 126 00:04:55,380 --> 00:04:57,790 Use the variable by itself it's value of, 127 00:04:57,790 --> 00:04:58,930 what's in the box. 128 00:04:58,930 --> 00:05:02,810 You take ampersand variable, address of, where is the box? 129 00:05:02,810 --> 00:05:04,370 And if you have a pointer variable, 130 00:05:04,370 --> 00:05:09,370 then the star says, the value that the pointer points to. 131 00:05:09,620 --> 00:05:14,020 And what we call this is an indirect memory read or write. 132 00:05:14,020 --> 00:05:15,360 What you see on line 27 133 00:05:15,360 --> 00:05:17,690 is an indirect memory read and write. 134 00:05:17,690 --> 00:05:21,120 A read/modify/write operation through pointer indirection. 135 00:05:21,120 --> 00:05:23,510 Remember I told you that the goroutine only has the ability 136 00:05:23,510 --> 00:05:27,190 to directly read and write to memory within its frame. 137 00:05:27,190 --> 00:05:28,870 Now when we made this call, 138 00:05:28,870 --> 00:05:31,630 this is no longer the active frame. 139 00:05:31,630 --> 00:05:33,790 This is now the active frame. 140 00:05:33,790 --> 00:05:37,830 The goroutine is operating within this sandbox right here, 141 00:05:37,830 --> 00:05:40,200 and now what we're able to do is say this, 142 00:05:40,200 --> 00:05:45,200 the goroutine still performs the direct memory read. 143 00:05:46,880 --> 00:05:49,820 Even though this is now still the active frame, right? 144 00:05:49,820 --> 00:05:53,200 Remember again, this is our active frame, right here. 145 00:05:53,200 --> 00:05:57,350 Our goroutine is operating within this sandbox right here. 146 00:05:57,350 --> 00:06:00,170 And in order for this goroutine to be able to access 147 00:06:00,170 --> 00:06:02,150 anything outside of its sandbox, 148 00:06:02,150 --> 00:06:06,820 it still must perform a read of the address. 149 00:06:06,820 --> 00:06:07,950 Remember that the goroutine 150 00:06:07,950 --> 00:06:10,550 only has direct memory access to the frame. 151 00:06:10,550 --> 00:06:12,160 If you want the goroutine to be able to access 152 00:06:12,160 --> 00:06:15,270 memory outside of the frame, you must share the address 153 00:06:15,270 --> 00:06:17,040 of that memory location to it, 154 00:06:17,040 --> 00:06:19,000 so it can be done in a safe way. 155 00:06:19,000 --> 00:06:21,930 And so now on line 28 what we have here 156 00:06:21,930 --> 00:06:26,930 is an indirect memory read/modify/write over here. 157 00:06:27,040 --> 00:06:28,720 And now what we're able to do 158 00:06:28,720 --> 00:06:32,200 is modify that memory outside of our frame. 159 00:06:32,200 --> 00:06:35,890 The pointer gives us this capability. 160 00:06:35,890 --> 00:06:39,590 However, there's a huge cost to pointers. 161 00:06:39,590 --> 00:06:41,260 Remember now we've just walked away 162 00:06:41,260 --> 00:06:45,010 from our mutation isolation, our immutability. 163 00:06:45,010 --> 00:06:46,480 What we've done is set ourselves up 164 00:06:46,480 --> 00:06:50,030 for what we call side effects in our code. 165 00:06:50,030 --> 00:06:51,700 When we start mutating memory, 166 00:06:51,700 --> 00:06:53,560 we have to be very, very careful. 167 00:06:53,560 --> 00:06:54,790 But if we're mutating memory 168 00:06:54,790 --> 00:06:56,870 within the scope of value semantics, 169 00:06:56,870 --> 00:06:58,280 we're good, we're clean, 170 00:06:58,280 --> 00:07:02,000 we can't cause problems anywhere else except for ourselves. 171 00:07:02,000 --> 00:07:05,730 But when we start mutating memory around pointer semantics 172 00:07:05,730 --> 00:07:07,610 we have to be very careful. 173 00:07:07,610 --> 00:07:10,360 Because at some point we are going to return 174 00:07:10,360 --> 00:07:11,280 from this function. 175 00:07:11,280 --> 00:07:14,090 We're going to move out of this program boundary, 176 00:07:14,090 --> 00:07:17,410 and we're gonna move back into this program boundary. 177 00:07:17,410 --> 00:07:19,470 Again, this being the active frame 178 00:07:19,470 --> 00:07:21,200 this is what we're operating on. 179 00:07:21,200 --> 00:07:25,080 And when we come back, we may not have realized 180 00:07:25,080 --> 00:07:27,390 that the goroutine or some other goroutine 181 00:07:27,390 --> 00:07:29,610 in a multi-threaded piece of software 182 00:07:29,610 --> 00:07:32,610 has gone behind the scenes and has mutated this data. 183 00:07:32,610 --> 00:07:36,190 It's not necessarily clean anymore, it's dirty. 184 00:07:36,190 --> 00:07:37,830 And if we're not aware of that, 185 00:07:37,830 --> 00:07:40,150 this can cause huge side effects. 186 00:07:40,150 --> 00:07:43,598 And in a multi-threaded software it could cause data races. 187 00:07:43,598 --> 00:07:47,810 Functional programming languages try to reduce 188 00:07:47,810 --> 00:07:51,150 the side effects by not giving you pointer semantics at all. 189 00:07:51,150 --> 00:07:53,160 Everything is value semantics. 190 00:07:53,160 --> 00:07:55,250 But remember the cost of value semantic 191 00:07:55,250 --> 00:07:57,530 is inefficiency with the data. 192 00:07:57,530 --> 00:07:59,840 There are times where it's just more efficient, 193 00:07:59,840 --> 00:08:02,640 simpler, to have one piece of data and that's it, 194 00:08:02,640 --> 00:08:05,000 and share it across your program. 195 00:08:05,000 --> 00:08:07,360 We're gonna continue to talk throughout the class 196 00:08:07,360 --> 00:08:09,450 when to use value, and when to use pointer semantics, 197 00:08:09,450 --> 00:08:10,610 I promise you. 198 00:08:10,610 --> 00:08:13,150 Right now we're still very focused on mechanics 199 00:08:13,150 --> 00:08:15,370 and some base semantics. 200 00:08:15,370 --> 00:08:18,580 But this class is going to, over the course of time, 201 00:08:18,580 --> 00:08:19,990 as we continue to go farther, 202 00:08:19,990 --> 00:08:22,750 try to teach you when to use one semantic over the other. 203 00:08:22,750 --> 00:08:25,250 There's just still more that I have to teach you. 204 00:08:25,250 --> 00:08:27,543 And so as I run this program here, 205 00:08:28,380 --> 00:08:30,810 you will see now that on the return 206 00:08:30,810 --> 00:08:34,710 we've mutated the memory in the frame above us. 207 00:08:34,710 --> 00:08:38,060 And now when we come back up, we now see that mutation. 208 00:08:38,060 --> 00:08:39,990 This is technically a side effect. 209 00:08:39,990 --> 00:08:43,580 We have mutated memory outside of our isolated space, 210 00:08:43,580 --> 00:08:47,290 our safe space, and have mutated something out here. 211 00:08:47,290 --> 00:08:50,340 This is gonna require a lot more care. 212 00:08:50,340 --> 00:08:54,250 And you can see here that now that we're here it's all gone. 213 00:08:54,250 --> 00:08:56,730 Now, there's one more thing I want to talk to you about 214 00:08:56,730 --> 00:08:58,690 as it relates to what we've seen here. 215 00:08:58,690 --> 00:09:01,500 I keep drawing for you the active frame. 216 00:09:01,500 --> 00:09:03,040 One thing that's very important, 217 00:09:03,040 --> 00:09:04,910 is I want you to come to the realization 218 00:09:04,910 --> 00:09:09,280 that any memory below the active frame 219 00:09:09,280 --> 00:09:11,520 is not valid memory. 220 00:09:11,520 --> 00:09:14,100 None of this memory is valid. 221 00:09:14,100 --> 00:09:17,060 If you noticed that we've been working the stack down, 222 00:09:17,060 --> 00:09:21,380 now that is a silly implementation detail. 223 00:09:21,380 --> 00:09:22,570 We could have done it any other way. 224 00:09:22,570 --> 00:09:24,770 Just historically this is how it's done. 225 00:09:24,770 --> 00:09:27,620 But I want you to understand that as we make function calls 226 00:09:27,620 --> 00:09:29,390 we are going deeper into the stack. 227 00:09:29,390 --> 00:09:31,980 As we return we are coming back up the stack. 228 00:09:31,980 --> 00:09:34,340 There are stack and frame pointers that allow us 229 00:09:34,340 --> 00:09:37,270 to identify where the active frame is. 230 00:09:37,270 --> 00:09:39,160 And in this case, what I want us to understand is that 231 00:09:39,160 --> 00:09:41,200 anything below the active frame 232 00:09:41,200 --> 00:09:43,140 this memory is no longer valid. 233 00:09:43,140 --> 00:09:44,880 It's no longer in play. 234 00:09:44,880 --> 00:09:47,500 The active frame and memory above has always 235 00:09:47,500 --> 00:09:50,530 got a level of integrity because we can continue to go up, 236 00:09:50,530 --> 00:09:52,970 but going down causes problems. 237 00:09:52,970 --> 00:09:56,990 Remember, we have the concept of zero value. 238 00:09:56,990 --> 00:09:59,930 And zero value is a very powerful concept in Go. 239 00:09:59,930 --> 00:10:03,760 Think about it, I'm back up in main right now. 240 00:10:03,760 --> 00:10:05,500 We've done this mutation. 241 00:10:05,500 --> 00:10:09,050 But what happens when main makes another function call? 242 00:10:09,050 --> 00:10:11,000 When main makes the next function call, 243 00:10:11,000 --> 00:10:14,220 it's going to need another frame. 244 00:10:14,220 --> 00:10:18,550 And when it takes that frame it's going to clean it up. 245 00:10:18,550 --> 00:10:21,150 This is why I wanna stress 246 00:10:21,150 --> 00:10:23,080 that memory below the active frame 247 00:10:23,080 --> 00:10:27,250 no longer has integrity because it's going to be reused. 248 00:10:27,250 --> 00:10:30,810 So we wanna keep that idea as well as we continue 249 00:10:30,810 --> 00:10:32,190 to learn about our value 250 00:10:32,190 --> 00:10:34,653 and our pointer semantics in these stacks.