1 00:00:06,560 --> 00:00:07,540 - Pointers. 2 00:00:07,540 --> 00:00:09,740 This is one of the most important sections we're gonna have 3 00:00:09,740 --> 00:00:12,870 in the class, it's really gonna help us learn 4 00:00:12,870 --> 00:00:14,700 how we can look at the impact that our code 5 00:00:14,700 --> 00:00:15,730 is having on the machine. 6 00:00:15,730 --> 00:00:18,350 Remember, I said that performance or the lack of performance 7 00:00:18,350 --> 00:00:21,060 is gonna come from four places. 8 00:00:21,060 --> 00:00:23,720 One is latency around networking, disk I/O, 9 00:00:23,720 --> 00:00:25,410 that type of dial, we're not gonna really talk 10 00:00:25,410 --> 00:00:26,800 about that in this class. 11 00:00:26,800 --> 00:00:30,310 The second one was around allocations and memory, 12 00:00:30,310 --> 00:00:32,100 garbage collection, this is where we're gonna learn 13 00:00:32,100 --> 00:00:34,100 how all of that stuff works. 14 00:00:34,100 --> 00:00:36,580 The third thing, again, was how we access data 15 00:00:36,580 --> 00:00:38,760 and eventually algorithm efficiency. 16 00:00:38,760 --> 00:00:41,220 This is our beginnings of being able to understand 17 00:00:41,220 --> 00:00:43,310 the impact that our code is having 18 00:00:43,310 --> 00:00:46,330 on the machine as it relates to memory. 19 00:00:46,330 --> 00:00:49,010 Let's start with the idea that everything 20 00:00:49,010 --> 00:00:51,970 in Go is pass by value. 21 00:00:51,970 --> 00:00:55,870 When I say pass by value, what I mean is wizzywig. 22 00:00:55,870 --> 00:00:58,700 What you see is what you get. 23 00:00:58,700 --> 00:01:02,200 I wanna give you an initial example of what we mean 24 00:01:02,200 --> 00:01:05,628 by pass by value and this idea that the wizzywig allows 25 00:01:05,628 --> 00:01:08,170 us to truly understand the impact 26 00:01:08,170 --> 00:01:10,100 that our program is having. 27 00:01:10,100 --> 00:01:13,770 Before I can really dive into this code, 28 00:01:13,770 --> 00:01:16,080 there's a couple things I wanna share with you upfront. 29 00:01:16,080 --> 00:01:18,440 We're gonna talk in a much deeper detail 30 00:01:18,440 --> 00:01:20,910 when we get to the concurrency sections. 31 00:01:20,910 --> 00:01:23,760 But, it's gonna help us to understand the impacts here 32 00:01:23,760 --> 00:01:25,860 on this code and the things that we're gonna 33 00:01:25,860 --> 00:01:27,710 be doing moving forward. 34 00:01:27,710 --> 00:01:29,380 Let's start with this. 35 00:01:29,380 --> 00:01:31,403 When your Go program starts up, 36 00:01:32,580 --> 00:01:37,140 it's gonna be given a P or a logical processor 37 00:01:37,140 --> 00:01:40,580 for every core that's identified on the host machine. 38 00:01:40,580 --> 00:01:42,860 From a playground perspective, or single-threaded, 39 00:01:42,860 --> 00:01:45,830 that is one core or one P. 40 00:01:45,830 --> 00:01:49,860 That P is given a real live operating system 41 00:01:49,860 --> 00:01:51,470 thread that we call M. 42 00:01:51,470 --> 00:01:54,830 I promise, I'm gonna be going much deeper into this stuff 43 00:01:54,830 --> 00:01:57,650 when we get to the concurrency sections, don't skip ahead. 44 00:01:57,650 --> 00:01:59,320 Stay with me right here. 45 00:01:59,320 --> 00:02:02,910 That M is gonna still be scheduled by the operating system 46 00:02:02,910 --> 00:02:07,040 scheduler on a particular core, and we get one more thing 47 00:02:07,040 --> 00:02:11,080 from the run time, and that is our goroutine. 48 00:02:11,080 --> 00:02:13,030 There it is, our G, and if you've ever heard 49 00:02:13,030 --> 00:02:16,450 of coroutines before, goroutines are coroutines, 50 00:02:16,450 --> 00:02:18,830 it's just Go changed the C to a G. 51 00:02:18,830 --> 00:02:21,430 With that said, what's important here right now 52 00:02:21,430 --> 00:02:24,220 is the idea of a path of execution. 53 00:02:24,220 --> 00:02:27,290 Threads are our path of execution 54 00:02:27,290 --> 00:02:28,920 at the operating system level. 55 00:02:28,920 --> 00:02:32,230 All of the code you're writing at some point gets into 56 00:02:32,230 --> 00:02:34,180 machine code, and the operating system's job 57 00:02:34,180 --> 00:02:36,980 is to choose a path of execution, a thread to execute 58 00:02:36,980 --> 00:02:39,760 those instructions one after the other. 59 00:02:39,760 --> 00:02:42,050 Starting from main, bop, bop, bop, bop, bop. 60 00:02:42,050 --> 00:02:43,520 That's the job of the thread. 61 00:02:43,520 --> 00:02:45,550 The operating system schedules threads. 62 00:02:45,550 --> 00:02:49,140 But, what's important here is the data structures now. 63 00:02:49,140 --> 00:02:50,980 There's three areas of memory that we may 64 00:02:50,980 --> 00:02:52,610 talk about throughout the class. 65 00:02:52,610 --> 00:02:56,180 There's the data segment, there's stacks, 66 00:02:56,180 --> 00:02:57,710 and there are heaps. 67 00:02:57,710 --> 00:02:59,930 The data segment's usually reserved for your 68 00:02:59,930 --> 00:03:02,360 global variables, your read-only values, 69 00:03:02,360 --> 00:03:05,050 we don't care about that so much today. 70 00:03:05,050 --> 00:03:07,593 What we're gonna focus on is stacks and heaps. 71 00:03:07,593 --> 00:03:12,593 A stack is a data structure that every thread is given. 72 00:03:12,930 --> 00:03:15,930 At the operating system level, your stack 73 00:03:15,930 --> 00:03:19,050 is a contiguous block of memory and usually 74 00:03:19,050 --> 00:03:21,570 it's allocated to be one meg. 75 00:03:21,570 --> 00:03:24,700 One meg of memory for every stack, 76 00:03:24,700 --> 00:03:26,090 and therefore for every thread. 77 00:03:26,090 --> 00:03:28,200 If you had 10,000 threads, you can add that up. 78 00:03:28,200 --> 00:03:29,920 That's 10,000 megs of memory 79 00:03:29,920 --> 00:03:32,320 immediately being used out of the box. 80 00:03:32,320 --> 00:03:34,350 This concept of a stack is coming to us 81 00:03:34,350 --> 00:03:35,780 all the way through the hardware. 82 00:03:35,780 --> 00:03:37,580 The hardware wants this stuff. 83 00:03:37,580 --> 00:03:40,140 It really helps simplify our programming models 84 00:03:40,140 --> 00:03:42,260 down there, and it's really gonna help us, too, 85 00:03:42,260 --> 00:03:44,360 in our programming models, as we're gonna see 86 00:03:44,360 --> 00:03:47,120 again to understand cost and what's happening. 87 00:03:47,120 --> 00:03:49,320 Since an M, or an operating system thread, 88 00:03:49,320 --> 00:03:51,560 is a path of execution, and it has a stack, 89 00:03:51,560 --> 00:03:54,350 and it needs that stack in order to do its job, 90 00:03:54,350 --> 00:03:58,660 our G, which is our path of execution at Go's level. 91 00:03:58,660 --> 00:04:00,860 Gs are very much like Ms, we could almost, 92 00:04:00,860 --> 00:04:03,370 at this point, say that they're the same 93 00:04:03,370 --> 00:04:05,830 but this is above the operating system. 94 00:04:05,830 --> 00:04:08,750 A G has a stack of memory, too. 95 00:04:08,750 --> 00:04:12,640 Except in Go today, that stack is 2K in size. 96 00:04:12,640 --> 00:04:13,473 2K. 97 00:04:13,473 --> 00:04:15,810 It was 4K for a long time. 98 00:04:15,810 --> 00:04:16,990 Today it's 2K. 99 00:04:16,990 --> 00:04:21,170 Notice how much smaller, and I mean significantly smaller, 100 00:04:21,170 --> 00:04:24,130 the stack is for a goroutine as it relates 101 00:04:24,130 --> 00:04:25,780 to an operating system. 102 00:04:25,780 --> 00:04:27,350 That's important, because we wanna be able to have 103 00:04:27,350 --> 00:04:29,280 a lot of goroutines in our program. 104 00:04:29,280 --> 00:04:31,200 Lots of paths of execution running. 105 00:04:31,200 --> 00:04:35,060 Remember, Go is focused both on integrity and minimizing 106 00:04:35,060 --> 00:04:37,810 the use of resources throughout the running program. 107 00:04:37,810 --> 00:04:40,360 This is one of those areas where we're seeing that. 108 00:04:41,753 --> 00:04:43,740 When our Go program starts up, we get a G. 109 00:04:43,740 --> 00:04:45,570 Our G is our path of execution. 110 00:04:45,570 --> 00:04:48,570 Its job is to execute every single instruction 111 00:04:48,570 --> 00:04:49,510 that we've written. 112 00:04:49,510 --> 00:04:52,730 The M is gonna host itself on top of the M 113 00:04:52,730 --> 00:04:55,490 to actually get that happening at the hardware level. 114 00:04:55,490 --> 00:04:58,540 What we have is this 2K stack, and this is what's important 115 00:04:58,540 --> 00:05:01,130 here, this is what we're gonna be talking about. 116 00:05:01,130 --> 00:05:04,370 By the time the goroutine that was created for this 117 00:05:04,370 --> 00:05:08,210 Go program wants to execute main, it's already executed 118 00:05:08,210 --> 00:05:10,010 a bunch of code from the run time. 119 00:05:10,010 --> 00:05:12,320 Eventually is says hey, I wanna execute 120 00:05:12,320 --> 00:05:14,860 the main function now, we're ready. 121 00:05:14,860 --> 00:05:16,483 This is what is going to happen. 122 00:05:17,860 --> 00:05:21,600 As the goroutine executes code and starts jumping 123 00:05:21,600 --> 00:05:25,320 between functions, this stack becomes critical 124 00:05:25,320 --> 00:05:27,060 to make all that happen. 125 00:05:27,060 --> 00:05:31,070 Eventually, the Go routine says I want to execute 126 00:05:31,070 --> 00:05:34,520 main, and any time a goroutine makes a function call, 127 00:05:34,520 --> 00:05:37,020 what it's going to do is take some memory off the stack. 128 00:05:37,020 --> 00:05:39,440 We call this a frame of memory. 129 00:05:39,440 --> 00:05:43,700 It's gonna slice a frame of memory off the stack 130 00:05:43,700 --> 00:05:47,500 so it can now execute the code that you see 131 00:05:47,500 --> 00:05:49,363 here inside of main. 132 00:05:49,363 --> 00:05:52,910 What I want you to understand right now is that 133 00:05:52,910 --> 00:05:55,330 in order to execute this data transformation, 134 00:05:55,330 --> 00:05:56,930 we have to be able to read and write memory. 135 00:05:56,930 --> 00:05:59,140 Remember, every line of code we write 136 00:05:59,140 --> 00:06:01,380 is either reading memory or writing memory. 137 00:06:01,380 --> 00:06:03,450 Obviously, also allocating at some point. 138 00:06:03,450 --> 00:06:07,340 It's doing those three things, and what's important here 139 00:06:07,340 --> 00:06:12,340 is that the goroutine only has direct access to memory. 140 00:06:12,830 --> 00:06:14,390 Let's think about this for a second. 141 00:06:14,390 --> 00:06:19,010 The goroutine only has direct access to memory 142 00:06:19,010 --> 00:06:22,040 for the frame that it is operating on. 143 00:06:22,040 --> 00:06:23,540 It wants to execute main. 144 00:06:23,540 --> 00:06:25,410 This is now our active frame. 145 00:06:25,410 --> 00:06:26,243 Here it is. 146 00:06:26,243 --> 00:06:29,400 The goroutine is now executing within this context, 147 00:06:29,400 --> 00:06:31,720 and this is, for our purposes right now, 148 00:06:31,720 --> 00:06:34,100 the only memory the goroutine 149 00:06:34,100 --> 00:06:36,330 can read and write to directly. 150 00:06:36,330 --> 00:06:37,163 This is it. 151 00:06:37,163 --> 00:06:39,170 What does that mean to us? 152 00:06:39,170 --> 00:06:42,320 What it means is if this data transformation 153 00:06:42,320 --> 00:06:44,570 has to be executed by the goroutine, 154 00:06:44,570 --> 00:06:47,420 and it can only operate within the scope of memory 155 00:06:47,420 --> 00:06:50,020 within this frame, it means all of the data 156 00:06:50,020 --> 00:06:51,700 that the goroutine needs to perform this 157 00:06:51,700 --> 00:06:54,520 data transformation has to be in here. 158 00:06:54,520 --> 00:06:55,393 This frame. 159 00:06:56,350 --> 00:07:00,810 If we look on line 10, what we see is a variable declaration 160 00:07:00,810 --> 00:07:03,550 of count assigned to the value of 10. 161 00:07:03,550 --> 00:07:05,350 We basically are now gonna be allocating 162 00:07:05,350 --> 00:07:09,070 our four bytes of memory right here inside this frame. 163 00:07:09,070 --> 00:07:11,750 It has to be inside this frame, because if it's not, 164 00:07:11,750 --> 00:07:14,290 the goroutine can't access it. 165 00:07:14,290 --> 00:07:16,740 Understand that this frame is serving 166 00:07:16,740 --> 00:07:18,740 a really important purpose. 167 00:07:18,740 --> 00:07:22,760 It's creating a sandbox, a layer of isolation. 168 00:07:22,760 --> 00:07:26,360 It's giving us a sense of immutability 169 00:07:26,360 --> 00:07:30,350 that the goroutine can only mutate or cause 170 00:07:30,350 --> 00:07:33,550 problems here and nowhere else in our code. 171 00:07:33,550 --> 00:07:35,830 This is very, very powerful constructs 172 00:07:35,830 --> 00:07:38,300 that we're gonna wanna leverage and it starts 173 00:07:38,300 --> 00:07:42,080 to allow us to talk about things like semantics. 174 00:07:42,080 --> 00:07:45,560 You're gonna hear me use the words mechanics and semantics. 175 00:07:45,560 --> 00:07:47,590 When I talk about mechanics, I'm talking about 176 00:07:47,590 --> 00:07:49,000 how things work. 177 00:07:49,000 --> 00:07:50,960 When I talk about semantics, I'm talking about 178 00:07:50,960 --> 00:07:53,150 how things behave. 179 00:07:53,150 --> 00:07:56,440 The semantics are gonna let us understand 180 00:07:56,440 --> 00:07:59,370 what the behavior is, the impact we're gonna have. 181 00:07:59,370 --> 00:08:01,870 The mechanics are gonna allow us to visualize 182 00:08:01,870 --> 00:08:03,170 and see how all that works. 183 00:08:03,170 --> 00:08:04,440 We need both. 184 00:08:04,440 --> 00:08:05,370 The semantics, though, 185 00:08:05,370 --> 00:08:08,420 are very, very important and powerful. 186 00:08:08,420 --> 00:08:11,280 What we're looking at so far here is that we've created 187 00:08:11,280 --> 00:08:15,680 a value of type Int, its value is 10, it has been 188 00:08:15,680 --> 00:08:18,410 allocated or created within the frame here 189 00:08:18,410 --> 00:08:20,130 because this is the only place the goroutine 190 00:08:20,130 --> 00:08:22,270 can operate in terms of memory. 191 00:08:22,270 --> 00:08:23,880 On line 13, we're doing two things. 192 00:08:23,880 --> 00:08:26,220 I wanna bring everything back to English. 193 00:08:26,220 --> 00:08:30,250 On line 13, what you're gonna see is that I'm asking us 194 00:08:30,250 --> 00:08:34,060 to display the value of count. 195 00:08:34,060 --> 00:08:35,640 Any time I use the variable's name I want 196 00:08:35,640 --> 00:08:37,530 us to think value of. 197 00:08:37,530 --> 00:08:39,870 What's in the box? 198 00:08:39,870 --> 00:08:43,170 Over here, you can see I'm using the ampersand operator. 199 00:08:43,170 --> 00:08:45,470 Ampersand operator isn't unique to Go. 200 00:08:45,470 --> 00:08:47,270 Many programming languages have used it, 201 00:08:47,270 --> 00:08:49,420 and it usually means the same thing. 202 00:08:49,420 --> 00:08:52,060 Address of, where is the box? 203 00:08:52,060 --> 00:08:55,820 Hey, if you got a box in memory, it's got to be somewhere. 204 00:08:55,820 --> 00:08:58,040 We're gonna be using hexadecimal numbers for this. 205 00:08:58,040 --> 00:09:01,110 We only have to worry about looking at the last four. 206 00:09:01,110 --> 00:09:03,653 I could pretend that this is an address F1BC. 207 00:09:04,888 --> 00:09:06,680 Again, we're using hexadecimal numbers, cause it's just 208 00:09:06,680 --> 00:09:09,380 more efficient when you have these very large numbers 209 00:09:09,380 --> 00:09:10,523 which are addresses. 210 00:09:12,220 --> 00:09:13,640 Value of, what's in the box? 211 00:09:13,640 --> 00:09:15,530 That's the variable and only the variable. 212 00:09:15,530 --> 00:09:18,880 Ampersand variable, address of, where is the box? 213 00:09:18,880 --> 00:09:21,330 It's gotta be located somewhere in memory. 214 00:09:21,330 --> 00:09:23,000 It's gonna be a memory address. 215 00:09:23,000 --> 00:09:24,140 There it is. 216 00:09:24,140 --> 00:09:26,530 I want you to look on line 16. 217 00:09:26,530 --> 00:09:30,200 In line 16, we're about to make another function call. 218 00:09:30,200 --> 00:09:32,613 I want you to think about this for a second. 219 00:09:33,700 --> 00:09:37,570 Every time you make a function call, what we're really doing 220 00:09:37,570 --> 00:09:41,150 is crossing over a program boundary. 221 00:09:41,150 --> 00:09:43,790 Program boundaries are important to identify, 222 00:09:43,790 --> 00:09:46,290 because in this case, this program boundary, 223 00:09:46,290 --> 00:09:48,380 this function call, means that we're gonna 224 00:09:48,380 --> 00:09:51,627 be moving out of this sandbox or frame 225 00:09:51,627 --> 00:09:54,590 and we're gonna be moving into a new one. 226 00:09:54,590 --> 00:09:57,320 Every time we call a function, what's going to happen 227 00:09:57,320 --> 00:10:01,470 is we're going to slice a new frame off the stack. 228 00:10:01,470 --> 00:10:04,410 This is now going to be the active frame. 229 00:10:04,410 --> 00:10:06,750 Our goroutine is now going to be operating 230 00:10:06,750 --> 00:10:10,340 within this sandbox, this level of isolation. 231 00:10:10,340 --> 00:10:13,750 Which once again means that we're gonna execute this code 232 00:10:13,750 --> 00:10:14,860 inside of increment. 233 00:10:14,860 --> 00:10:19,510 We're gonna perform this new data transformation, 234 00:10:19,510 --> 00:10:22,740 then the data the goroutine needs to perform 235 00:10:22,740 --> 00:10:25,710 this transformation better be inside of this frame 236 00:10:25,710 --> 00:10:28,620 cause this is the only place we can operate in. 237 00:10:28,620 --> 00:10:31,620 This is where the idea of parameters comes from. 238 00:10:31,620 --> 00:10:34,270 We have been using parameters our whole programming lives. 239 00:10:34,270 --> 00:10:36,870 We learned about API design. 240 00:10:36,870 --> 00:10:39,040 We've done all of these things, but I wanna show you 241 00:10:39,040 --> 00:10:42,180 the mechanics behind it because without the mechanics 242 00:10:42,180 --> 00:10:45,890 of parameters, we wouldn't be able to encapsulate at all. 243 00:10:45,890 --> 00:10:48,930 These parameters are really serving a mechanical purpose 244 00:10:48,930 --> 00:10:52,040 on top of our design purpose, and that is to get data 245 00:10:52,040 --> 00:10:55,660 inside of this new frame so the goroutine can operate 246 00:10:55,660 --> 00:10:59,000 this new data transformation in a level of isolation 247 00:10:59,000 --> 00:11:01,630 with a level of immutability. 248 00:11:01,630 --> 00:11:06,150 What we're doing on line 16 is passing the value 249 00:11:06,150 --> 00:11:08,910 of count across this programming boundary. 250 00:11:08,910 --> 00:11:11,110 Because everything in Go is passed by value, 251 00:11:11,110 --> 00:11:13,880 what that means is that we're gonna make a copy 252 00:11:13,880 --> 00:11:17,160 of the data as it goes across the boundary. 253 00:11:17,160 --> 00:11:20,110 You're gonna hear me start using three different terms. 254 00:11:20,110 --> 00:11:22,520 You're gonna hear me use the word data, 255 00:11:22,520 --> 00:11:23,900 and data's what we're working with. 256 00:11:23,900 --> 00:11:25,390 Concrete data, if you don't understand the data, 257 00:11:25,390 --> 00:11:26,470 you don't understand the problem. 258 00:11:26,470 --> 00:11:29,200 There's two types of data that we operate with. 259 00:11:29,200 --> 00:11:32,780 It is the value itself, like this integer value 10, 260 00:11:32,780 --> 00:11:34,780 or it's the value's address. 261 00:11:34,780 --> 00:11:38,430 Yes, addresses are data, and I want you 262 00:11:38,430 --> 00:11:40,350 to always understand that. 263 00:11:40,350 --> 00:11:43,640 In this case, what we're passing across the program boundary 264 00:11:43,640 --> 00:11:46,730 is the value itself, which means we're making a copy 265 00:11:46,730 --> 00:11:48,360 of the value, the four bytes. 266 00:11:48,360 --> 00:11:50,430 We're gonna throw it over this program boundary, 267 00:11:50,430 --> 00:11:53,950 which means that those four bytes have to end up, now, 268 00:11:53,950 --> 00:11:56,860 inside this frame as well. 269 00:11:56,860 --> 00:12:00,280 This is where your parameters come from. 270 00:12:00,280 --> 00:12:01,550 This parameter we're declaring 271 00:12:01,550 --> 00:12:04,040 inside of inc, increment, sorry. 272 00:12:04,040 --> 00:12:08,820 Inc int, what that is there for is to capture 273 00:12:08,820 --> 00:12:12,290 or hold that value we're throwing over the program boundary 274 00:12:12,290 --> 00:12:16,330 so the goroutine can operate this data transformation. 275 00:12:16,330 --> 00:12:18,240 This becomes inc. 276 00:12:18,240 --> 00:12:21,680 Passed by value means we make copies and we store copies. 277 00:12:21,680 --> 00:12:22,560 There it is. 278 00:12:22,560 --> 00:12:26,190 Now, the goroutine can operate within this function 279 00:12:26,190 --> 00:12:29,460 right here, which it is, and on line 27 what you see 280 00:12:29,460 --> 00:12:32,380 is a read-modify-write operation. 281 00:12:32,380 --> 00:12:34,790 Line 27, inc plus plus, which means that we 282 00:12:34,790 --> 00:12:38,750 are now mutating memory, but we're mutating it right here. 283 00:12:38,750 --> 00:12:42,530 What's really important is that this frame 284 00:12:42,530 --> 00:12:46,070 is allowing the goroutine to mutate memory 285 00:12:46,070 --> 00:12:50,890 without any cause of side effects throughout the program. 286 00:12:50,890 --> 00:12:54,150 The memory mutation is happening in isolation 287 00:12:54,150 --> 00:12:56,820 within our sandbox with a level of mutability 288 00:12:56,820 --> 00:12:59,470 in the sense that we don't affect anything else 289 00:12:59,470 --> 00:13:02,090 outside of this execution context. 290 00:13:02,090 --> 00:13:05,770 This is a very, very important and powerful mechanism. 291 00:13:05,770 --> 00:13:07,250 What we're really seeing here 292 00:13:07,250 --> 00:13:09,920 is what is called values semantics. 293 00:13:09,920 --> 00:13:13,760 We're gonna focus a lot in this class on the value 294 00:13:13,760 --> 00:13:16,990 and pointer semantics behavior that the language gives you. 295 00:13:16,990 --> 00:13:20,660 If you wanna write code in Go that is optimized 296 00:13:20,660 --> 00:13:22,870 for correctness, that you can read and understand 297 00:13:22,870 --> 00:13:24,487 the impact of things, then your value 298 00:13:24,487 --> 00:13:27,170 and your pointer semantics are everything. 299 00:13:27,170 --> 00:13:30,170 What we're looking at here is an example of value semantics. 300 00:13:31,690 --> 00:13:34,150 There's a value here in main for count. 301 00:13:34,150 --> 00:13:36,660 Now, we operate a different transformation 302 00:13:36,660 --> 00:13:39,370 around that data, and that means that every 303 00:13:39,370 --> 00:13:41,410 data transformation, every piece of code 304 00:13:41,410 --> 00:13:44,570 that's operating on it gets its own copy of the value. 305 00:13:44,570 --> 00:13:46,230 This is value semantics. 306 00:13:46,230 --> 00:13:47,970 It's very, very important. 307 00:13:47,970 --> 00:13:51,540 Value semantics has the benefit of again this idea 308 00:13:51,540 --> 00:13:53,210 of isolation and mutability. 309 00:13:53,210 --> 00:13:55,520 It's going to also, potentially, in many cases 310 00:13:55,520 --> 00:13:57,140 give us some performance. 311 00:13:57,140 --> 00:13:58,400 We're gonna talk about that. 312 00:13:58,400 --> 00:14:00,610 But, I told you engineering is not about 313 00:14:00,610 --> 00:14:03,660 just hacking code, it's about knowing the cost of things. 314 00:14:03,660 --> 00:14:07,050 Everything has a cost, nothing is free. 315 00:14:07,050 --> 00:14:11,010 So the question now is what is the cost of value semantics? 316 00:14:11,010 --> 00:14:14,450 One of the costs of value semantics is that we have 317 00:14:14,450 --> 00:14:18,350 multiple copies of the data throughout the program. 318 00:14:18,350 --> 00:14:22,380 There is no efficiency with the value semantics, 319 00:14:22,380 --> 00:14:24,770 and sometimes it can be very complicated 320 00:14:24,770 --> 00:14:26,650 to get a piece of data that's changed 321 00:14:26,650 --> 00:14:29,860 and to get that updated everywhere it needs to be. 322 00:14:29,860 --> 00:14:32,900 Our value semantics are very powerful semantics 323 00:14:32,900 --> 00:14:35,590 because it's gonna reduce things like side effects. 324 00:14:35,590 --> 00:14:36,530 We'll talk about that. 325 00:14:36,530 --> 00:14:39,010 It's giving us isolation, it's giving us these levels 326 00:14:39,010 --> 00:14:43,800 of immutability that are so important towards integrity. 327 00:14:43,800 --> 00:14:46,830 Sometimes, the inefficiency of value semantics 328 00:14:46,830 --> 00:14:49,760 might cause more complexity in the code. 329 00:14:49,760 --> 00:14:51,850 It might even cause some performance problems, 330 00:14:51,850 --> 00:14:54,430 and performance does matter. 331 00:14:54,430 --> 00:14:56,530 One of the things we've gotta learn is how to balance 332 00:14:56,530 --> 00:14:59,120 our value and our pointer semantics. 333 00:14:59,120 --> 00:15:02,940 Right now, all we're looking at here is the value semantics. 334 00:15:02,940 --> 00:15:06,750 When the increment function returns and we're back up 335 00:15:06,750 --> 00:15:10,360 in main, now what's going to happen is this goroutine 336 00:15:10,360 --> 00:15:14,170 is no longer operating in this active frame. 337 00:15:14,170 --> 00:15:16,210 This is now our active frame. 338 00:15:16,210 --> 00:15:19,490 The goroutine is now operating here, and if I were to run 339 00:15:19,490 --> 00:15:22,580 this program, what we're gonna see is that mutation 340 00:15:22,580 --> 00:15:27,420 that we made got isolated here, did not carry up or forward. 341 00:15:27,420 --> 00:15:29,780 Now, this piece of code is still operating 342 00:15:29,780 --> 00:15:31,010 on its own copy. 343 00:15:31,010 --> 00:15:32,950 This was operating on its own copy. 344 00:15:32,950 --> 00:15:34,820 We got the benefit of this mutation 345 00:15:34,820 --> 00:15:36,610 not affecting anything else. 346 00:15:36,610 --> 00:15:40,550 This is value semantics and this is a big part, again, 347 00:15:40,550 --> 00:15:42,610 of the beauty of the pass by value. 348 00:15:42,610 --> 00:15:44,573 What we see is what you get.