1 00:00:06,700 --> 00:00:08,200 - [Instructor] The Context package and Go 2 00:00:08,200 --> 00:00:11,620 is a very important package because it's really where we're 3 00:00:11,620 --> 00:00:14,530 gonna implement cancellation and deadlines. 4 00:00:14,530 --> 00:00:17,140 Remember your server can't take forever to do things. 5 00:00:17,140 --> 00:00:18,330 A request can't take forever, 6 00:00:18,330 --> 00:00:20,040 a task can't take forever. 7 00:00:20,040 --> 00:00:21,970 Your database calls, your network calls. 8 00:00:21,970 --> 00:00:24,350 If you allow things to take forever, 9 00:00:24,350 --> 00:00:26,980 you are eventually going to crash when life is bad. 10 00:00:26,980 --> 00:00:29,310 Timeouts, timeouts, timeouts, timeouts, 11 00:00:29,310 --> 00:00:30,802 timeouts, for everything. 12 00:00:30,802 --> 00:00:32,760 And the Context package is the solution. 13 00:00:32,760 --> 00:00:35,230 But Go made it very simple to create these paths 14 00:00:35,230 --> 00:00:37,110 of execution, these goroutines, 15 00:00:37,110 --> 00:00:40,160 it didn't really make it as simple to cancel them, 16 00:00:40,160 --> 00:00:42,400 so we've gotta learn how to use the Context package. 17 00:00:42,400 --> 00:00:44,470 And I'm gonna show you a little bit that, 18 00:00:44,470 --> 00:00:47,980 any API that you have that does any sort of AI, 19 00:00:47,980 --> 00:00:51,370 any sort of Io or eventually will do Io, 20 00:00:51,370 --> 00:00:54,400 should be taking Context as its first parameter. 21 00:00:54,400 --> 00:00:57,350 Now one of the other things that the Context package has 22 00:00:57,350 --> 00:01:00,700 is a generic value bag. 23 00:01:00,700 --> 00:01:02,930 Now I'm very afraid of the generic value bag 24 00:01:02,930 --> 00:01:06,970 because you don't wanna be using it for like requests, 25 00:01:06,970 --> 00:01:11,290 local, we used to call local thread storage right? 26 00:01:11,290 --> 00:01:15,370 You don't wanna be doing things like local request storage. 27 00:01:15,370 --> 00:01:18,570 You never wanna hide data in a context, 28 00:01:18,570 --> 00:01:20,360 but putting data in a context can help for things 29 00:01:20,360 --> 00:01:21,500 that functions don't need, 30 00:01:21,500 --> 00:01:23,090 we'll talk a little bit more about that. 31 00:01:23,090 --> 00:01:26,050 So first I wanna show you how to use the value bag, 32 00:01:26,050 --> 00:01:28,520 but we're gonna be very careful about when we use this. 33 00:01:28,520 --> 00:01:30,210 In code reviews if I see this being used, 34 00:01:30,210 --> 00:01:31,890 we're gonna be very clear, 35 00:01:31,890 --> 00:01:33,150 but we're storing things in there 36 00:01:33,150 --> 00:01:36,610 that aren't really necessary for the functioning of the app, 37 00:01:36,610 --> 00:01:38,740 it's more of for secondary stuff. 38 00:01:38,740 --> 00:01:40,960 Like reporting metrics, things like that. 39 00:01:40,960 --> 00:01:44,210 So the way the value bag works is, 40 00:01:44,210 --> 00:01:47,500 data is stored inside the context with a combination 41 00:01:47,500 --> 00:01:49,810 of a key, and then the value. 42 00:01:49,810 --> 00:01:51,900 But the key isn't just some value, 43 00:01:51,900 --> 00:01:54,220 it's also gonna be based on type. 44 00:01:54,220 --> 00:01:59,220 So the key is a type-based system where then we, 45 00:01:59,560 --> 00:02:01,190 based on some value, 46 00:02:01,190 --> 00:02:04,130 and then we store the value itself on that key. 47 00:02:04,130 --> 00:02:05,370 I didn't explain that very well. 48 00:02:05,370 --> 00:02:07,400 I'm gonna show it to you here, let me show you. 49 00:02:07,400 --> 00:02:08,730 So here's the idea. 50 00:02:08,730 --> 00:02:10,720 I've got a trace ID here. 51 00:02:10,720 --> 00:02:14,970 I've defined this type called TraceID based on a string. 52 00:02:14,970 --> 00:02:16,560 This is the data that we wanna store. 53 00:02:16,560 --> 00:02:19,660 Imagine we have a web service and we're generating 54 00:02:19,660 --> 00:02:21,840 a TraceID, a unique ID. 55 00:02:21,840 --> 00:02:24,050 That is something you probably wanna put in the Context. 56 00:02:24,050 --> 00:02:25,250 And pass that around. 57 00:02:25,250 --> 00:02:28,800 So we've got a TraceID as a string and then I've got a key. 58 00:02:28,800 --> 00:02:31,830 Now the key is based on an integer, 59 00:02:31,830 --> 00:02:33,360 but the type we're gonna be using for a key 60 00:02:33,360 --> 00:02:35,640 is this thing called TraceIDKey. 61 00:02:35,640 --> 00:02:39,010 Based on an int, we're gonna be using this new name type. 62 00:02:39,010 --> 00:02:43,420 Now I go ahead in this program and I create my TraceID. 63 00:02:43,420 --> 00:02:46,070 There it is, there's my TraceID, it's my string. 64 00:02:46,070 --> 00:02:49,680 I can imagine here that here is that string value 65 00:02:49,680 --> 00:02:54,210 for my TraceID and we're calling this right here, 66 00:02:54,210 --> 00:02:56,720 TraceID, there it is. 67 00:02:56,720 --> 00:02:59,640 And I've got this value in here, 68 00:02:59,640 --> 00:03:02,800 which is really representing a UUID right? 69 00:03:02,800 --> 00:03:04,350 There it is. 70 00:03:04,350 --> 00:03:07,470 Now I generate this key, 71 00:03:07,470 --> 00:03:11,960 but understand that the key, the key that I have here, 72 00:03:11,960 --> 00:03:15,220 which is a constant, which is the value of zero, 73 00:03:15,220 --> 00:03:17,020 isn't really an int. 74 00:03:17,020 --> 00:03:21,420 It's really this Trace, let's spell this right. 75 00:03:21,420 --> 00:03:23,170 It's really not an integer, 76 00:03:23,170 --> 00:03:27,870 it's TraceIDKey, remember that. 77 00:03:27,870 --> 00:03:30,950 This value isn't an integer it's a TraceIDKey. 78 00:03:30,950 --> 00:03:31,783 Okay brilliant. 79 00:03:31,783 --> 00:03:32,733 Now what happens? 80 00:03:34,090 --> 00:03:36,683 If we're gonna work with Context we need a context 81 00:03:36,683 --> 00:03:38,350 and when you don't have a context you gotta start 82 00:03:38,350 --> 00:03:40,040 with a parent context. 83 00:03:40,040 --> 00:03:42,580 Now there's two ways to get to a parent context. 84 00:03:42,580 --> 00:03:45,760 We can use this function called Background 85 00:03:45,760 --> 00:03:47,910 out of the Context package, 86 00:03:47,910 --> 00:03:50,140 or you can use what's called TODO 87 00:03:51,190 --> 00:03:52,960 out of the Context package. 88 00:03:52,960 --> 00:03:54,200 Right here, TODO, 89 00:03:54,200 --> 00:03:56,020 that's also another function. 90 00:03:56,020 --> 00:03:57,900 When would you use one over the other? 91 00:03:57,900 --> 00:03:59,880 When you know you need a context but you're not sure 92 00:03:59,880 --> 00:04:01,350 where it's gonna come from, 93 00:04:01,350 --> 00:04:04,290 or how it's gonna be initially initialized, use TODO. 94 00:04:04,290 --> 00:04:06,380 It's a marker in your code to say, 95 00:04:06,380 --> 00:04:09,430 I've gotta come back here and TODO this, right? 96 00:04:09,430 --> 00:04:11,730 And a lot of times you don't really know what your 97 00:04:11,730 --> 00:04:13,220 timeout value should be at. 98 00:04:13,220 --> 00:04:15,890 You don't really know how things are gonna work with Context 99 00:04:15,890 --> 00:04:16,870 but you know you need it, 100 00:04:16,870 --> 00:04:19,690 you wanna lay it in early, very early. 101 00:04:19,690 --> 00:04:23,260 So TODO is something I probably use more than Background. 102 00:04:23,260 --> 00:04:26,700 But Background is your base parent context. 103 00:04:26,700 --> 00:04:29,603 You can think of Background from our perspective, 104 00:04:30,564 --> 00:04:34,760 as a value that's just kind of initialized and setup 105 00:04:34,760 --> 00:04:37,360 as an empty context. 106 00:04:37,360 --> 00:04:38,500 There's nothing in it. 107 00:04:38,500 --> 00:04:41,240 So this is our Background. 108 00:04:41,240 --> 00:04:44,970 Our Background context right here that we're using. 109 00:04:44,970 --> 00:04:48,700 Now Context uses value semantics okay? 110 00:04:48,700 --> 00:04:51,330 We pass a context in, we make changes to it, 111 00:04:51,330 --> 00:04:53,120 we get a new context out. 112 00:04:53,120 --> 00:04:54,980 We use value semantics. 113 00:04:54,980 --> 00:04:59,000 One of the reason we use value semantics with Context is, 114 00:04:59,000 --> 00:05:02,040 is because a context can change throughout 115 00:05:02,040 --> 00:05:04,330 a function call change. 116 00:05:04,330 --> 00:05:05,290 In other words, 117 00:05:05,290 --> 00:05:09,170 at the root of any particular set of function calls, 118 00:05:09,170 --> 00:05:12,590 you might start with that empty Background context. 119 00:05:12,590 --> 00:05:15,180 Then we're gonna pass over these program boundaries. 120 00:05:15,180 --> 00:05:18,290 Maybe we make another function call, and then this function, 121 00:05:18,290 --> 00:05:20,090 even though it starts with the empty, 122 00:05:20,090 --> 00:05:24,660 maybe it adds some timeout information like 10 milliseconds. 123 00:05:24,660 --> 00:05:27,280 Maybe we pass this context around 124 00:05:27,280 --> 00:05:28,940 to two different goroutines. 125 00:05:28,940 --> 00:05:31,880 Now we went from this one goroutine, 126 00:05:31,880 --> 00:05:33,260 to two goroutines right? 127 00:05:33,260 --> 00:05:35,900 We split this path of execution in parallel, 128 00:05:35,900 --> 00:05:38,710 and now things might be changing here. 129 00:05:38,710 --> 00:05:42,590 Now this side of the processing only wants to start using 130 00:05:42,590 --> 00:05:45,220 maybe five millisecond timeouts. 131 00:05:45,220 --> 00:05:47,930 So the value semantics are important because, 132 00:05:47,930 --> 00:05:51,780 as a context is changing, we get a new context, 133 00:05:51,780 --> 00:05:54,780 and then the way cancellation eventually starts to work, 134 00:05:54,780 --> 00:05:57,100 is if we cancel here, 135 00:05:57,100 --> 00:05:59,740 then we're gonna cancel down both paths. 136 00:05:59,740 --> 00:06:02,199 Or maybe we just cancel here, 137 00:06:02,199 --> 00:06:04,745 and we're only gonna cancel down this path. 138 00:06:04,745 --> 00:06:08,040 Value semantics are critical here and making sure 139 00:06:08,040 --> 00:06:11,770 that things are consistent as we make these function calls 140 00:06:11,770 --> 00:06:13,630 and we move down these paths of execution, 141 00:06:13,630 --> 00:06:15,053 and even if they split. 142 00:06:17,436 --> 00:06:20,460 This program is starting with the empty context, 143 00:06:20,460 --> 00:06:21,310 our parent context, 144 00:06:21,310 --> 00:06:24,169 we passed it into a function called WithValue. 145 00:06:24,169 --> 00:06:26,920 WithValue's how you add state to a context. 146 00:06:26,920 --> 00:06:29,470 You give it a key and you give it a value. 147 00:06:29,470 --> 00:06:31,630 Remember the key is based on a type. 148 00:06:31,630 --> 00:06:33,440 So remember what we did here. 149 00:06:33,440 --> 00:06:37,033 We started with the Background or the empty. 150 00:06:37,940 --> 00:06:41,330 The empty context and then what did we get back? 151 00:06:41,330 --> 00:06:44,970 We got a new context, this is our new context now, 152 00:06:44,970 --> 00:06:46,480 we don't care about the old one. 153 00:06:46,480 --> 00:06:49,220 And now the new context has everything the empty one has, 154 00:06:49,220 --> 00:06:53,140 which is nothing, and now what it has is our TraceID, 155 00:06:54,060 --> 00:06:57,090 and then here we're using value semantics again. 156 00:06:57,090 --> 00:07:02,090 So we've got a copy of that UUID and it's based on this key, 157 00:07:03,340 --> 00:07:07,340 which is our TraceIDKey of zero. 158 00:07:07,340 --> 00:07:10,413 That's it, that's what we've stored in the context now. 159 00:07:11,473 --> 00:07:14,270 To pull this data out of the context we're gonna use 160 00:07:14,270 --> 00:07:18,610 the value method off of this context. 161 00:07:18,610 --> 00:07:19,830 The value method. 162 00:07:19,830 --> 00:07:23,850 And the value method actually requires the key, 163 00:07:23,850 --> 00:07:26,070 but not the key value. 164 00:07:26,070 --> 00:07:29,890 It's going to want the key value based on the right type. 165 00:07:29,890 --> 00:07:34,890 So on line 33 I'm passing the key that we used okay, 166 00:07:35,350 --> 00:07:38,340 based on our type, TraceID is the type. 167 00:07:38,340 --> 00:07:39,480 The value is zero. 168 00:07:39,480 --> 00:07:44,130 And when I do that I will get back a copy, UUID, 169 00:07:44,130 --> 00:07:46,023 I will get back a copy. 170 00:07:46,912 --> 00:07:49,070 Again we're all using value semantics here. 171 00:07:49,070 --> 00:07:52,350 A copy of this, we'll get back our copy. 172 00:07:52,350 --> 00:07:57,340 But if you look on line 39, if I just use the value of zero, 173 00:07:57,340 --> 00:08:00,150 which in this case is the constant of kind int. 174 00:08:00,150 --> 00:08:02,300 So if I use an integer, 175 00:08:02,300 --> 00:08:06,890 if I use an integer-based zero, this is an int, 176 00:08:06,890 --> 00:08:10,870 not a TraceID-based value of zero, 177 00:08:10,870 --> 00:08:14,160 but an integer-based value of zero for my key, 178 00:08:14,160 --> 00:08:17,300 then that okay flag's going to be false. 179 00:08:17,300 --> 00:08:19,020 But we're using a blank identifier in this case 180 00:08:19,020 --> 00:08:20,180 'cause I don't care. 181 00:08:20,180 --> 00:08:23,480 It's gonna be false meaning that we didn't get this back. 182 00:08:23,480 --> 00:08:25,740 If I did have a variable where the blank identifier 183 00:08:25,740 --> 00:08:26,930 is on line 39, 184 00:08:26,930 --> 00:08:29,110 then that would be set to a zero value. 185 00:08:29,110 --> 00:08:32,090 So the only way to pull data out of this context 186 00:08:32,090 --> 00:08:33,830 is to not just have the right value, 187 00:08:33,830 --> 00:08:36,090 but have the right value and its right type. 188 00:08:36,090 --> 00:08:38,100 That's what this code here is showing you. 189 00:08:38,100 --> 00:08:40,300 And we've gotta be very, very careful when we store 190 00:08:40,300 --> 00:08:42,470 data int to this context. 191 00:08:42,470 --> 00:08:43,670 This is generic. 192 00:08:43,670 --> 00:08:46,330 We can't be hiding information in our software 193 00:08:46,330 --> 00:08:48,810 ever, ever, ever, so we gotta be very clear about 194 00:08:48,810 --> 00:08:49,970 what we're putting in there 195 00:08:49,970 --> 00:08:51,640 and then how we're taking it out. 196 00:08:51,640 --> 00:08:53,930 But this is how the value bag works with the 197 00:08:53,930 --> 00:08:57,480 WithValue function call and as you'll continue to see, 198 00:08:57,480 --> 00:09:01,300 everything here is value semantics with Context. 199 00:09:01,300 --> 00:09:04,343 Now, let me show you another API here. 200 00:09:05,440 --> 00:09:07,860 In this one what I'm gonna show you 201 00:09:09,034 --> 00:09:11,170 is the wait WithTimeout. 202 00:09:11,170 --> 00:09:14,500 There's actually four With functions here 203 00:09:14,500 --> 00:09:15,333 that you could use. 204 00:09:15,333 --> 00:09:17,340 WithCancel, WithDeadline, WithTimeout, WithValue, 205 00:09:18,490 --> 00:09:19,970 which we saw for the state. 206 00:09:19,970 --> 00:09:21,740 But when it comes to cancellation and deadline, 207 00:09:21,740 --> 00:09:23,570 we have Cancel, Deadline and Timeout. 208 00:09:23,570 --> 00:09:25,400 And they all kinda work the same so, 209 00:09:25,400 --> 00:09:28,910 I'm just gonna focus on Timeout and you'll know already 210 00:09:28,910 --> 00:09:31,990 how Deadline and Cancel work, 211 00:09:31,990 --> 00:09:33,480 and we'll explain that as well. 212 00:09:33,480 --> 00:09:35,750 So here's the idea. 213 00:09:35,750 --> 00:09:39,850 I'm gonna have some goroutine go off and do some work. 214 00:09:39,850 --> 00:09:43,333 And we're gonna be using that cancellation pattern. 215 00:09:45,100 --> 00:09:48,270 The idea now is that goroutine only has so much time 216 00:09:48,270 --> 00:09:49,900 to get the work done. 217 00:09:49,900 --> 00:09:52,140 So let's walk through this code. 218 00:09:52,140 --> 00:09:54,623 I set a duration, here it is. 219 00:09:55,968 --> 00:09:59,060 A duration of 150 milliseconds. 220 00:09:59,060 --> 00:10:02,010 That's what we're willing to wait okay? 221 00:10:02,010 --> 00:10:04,800 And then I go with Context WithTimeout. 222 00:10:04,800 --> 00:10:07,550 Now we're gonna use the Context Background 223 00:10:07,550 --> 00:10:09,880 as our empty base context. 224 00:10:09,880 --> 00:10:13,660 I pass the duration of 150 milliseconds, 225 00:10:13,660 --> 00:10:16,200 and we get back our new context. 226 00:10:16,200 --> 00:10:19,870 So let's think of this context now, as saying, 227 00:10:19,870 --> 00:10:24,870 that we have 150 millisecond Timeout to get things done. 228 00:10:25,980 --> 00:10:28,000 In other words in 150 milliseconds, 229 00:10:28,000 --> 00:10:31,390 this context would report the time is over. 230 00:10:31,390 --> 00:10:33,570 We've gotta stop doing what we're doing. 231 00:10:33,570 --> 00:10:36,600 Now it's very important that you look on line 26. 232 00:10:36,600 --> 00:10:38,431 Notice that WithTimeout, 233 00:10:38,431 --> 00:10:39,880 and this would be the same for the other two functions, 234 00:10:39,880 --> 00:10:41,420 WithDeadline and WithCancel, 235 00:10:41,420 --> 00:10:43,870 you get back a handler function called, 236 00:10:43,870 --> 00:10:45,380 we call it cancel. 237 00:10:45,380 --> 00:10:47,310 You have to call cancel. 238 00:10:47,310 --> 00:10:50,640 It must be called to clean up resources or you will leak. 239 00:10:50,640 --> 00:10:54,935 And so this pattern of calling WithTimeout, WithDeadline, 240 00:10:54,935 --> 00:10:57,970 WithCancel and then deferring the cancel, is critical. 241 00:10:57,970 --> 00:11:01,070 The goroutine that creates the context with one of these 242 00:11:01,070 --> 00:11:03,400 WithTimeout, WithDeadline functions, WithCancel, 243 00:11:03,400 --> 00:11:06,120 must also call cancel and it's okay for cancel 244 00:11:06,120 --> 00:11:07,580 to be called twice. 245 00:11:07,580 --> 00:11:08,900 Anytime you called cancel, 246 00:11:08,900 --> 00:11:10,910 you're immediately timing this thing out, 247 00:11:10,910 --> 00:11:12,640 like immediately we're timing it out. 248 00:11:12,640 --> 00:11:14,540 We're not gonna wait the full time. 249 00:11:14,540 --> 00:11:15,990 So we're deferring the cancel. 250 00:11:15,990 --> 00:11:18,200 It's very, very important. 251 00:11:18,200 --> 00:11:19,100 Notice what we do next. 252 00:11:19,100 --> 00:11:20,870 I create a buffer channel of one, 253 00:11:20,870 --> 00:11:23,720 because we want that delayed guarantee, 254 00:11:23,720 --> 00:11:27,200 and I go off and I create a goroutine. 255 00:11:27,200 --> 00:11:28,120 So here we are again. 256 00:11:28,120 --> 00:11:30,860 Here's our Manager goroutine, 257 00:11:30,860 --> 00:11:33,800 going off created the Employee goroutine. 258 00:11:33,800 --> 00:11:37,080 This Employee again is using that wait for request pattern, 259 00:11:37,080 --> 00:11:39,480 this is a fan-out pattern in a sense, 260 00:11:39,480 --> 00:11:42,470 where that Employee knows that there's some work 261 00:11:42,470 --> 00:11:43,303 it has to do. 262 00:11:43,303 --> 00:11:45,323 This is like a fan-out pattern except 263 00:11:45,323 --> 00:11:46,770 we're only fanning out one goroutine. 264 00:11:46,770 --> 00:11:48,170 Again, we can't, 265 00:11:48,170 --> 00:11:50,270 this goroutine can't cancel the work on its own, 266 00:11:50,270 --> 00:11:51,793 it's gonna require us. 267 00:11:52,900 --> 00:11:55,760 We're saying that this work is gonna be able to take 268 00:11:55,760 --> 00:11:58,560 50 milliseconds in this particular piece of code, 269 00:11:58,560 --> 00:12:02,060 which is well under the 150 that's here. 270 00:12:02,060 --> 00:12:06,010 And then once this is done, it will perform its send, 271 00:12:06,010 --> 00:12:08,320 on line 38, with the result, 272 00:12:08,320 --> 00:12:11,060 which is that data value, result right there. 273 00:12:11,060 --> 00:12:12,130 Okay brilliant. 274 00:12:12,130 --> 00:12:15,150 Now while this goroutine is off doing its work, 275 00:12:15,150 --> 00:12:17,210 in this case the 50 milliseconds of work, 276 00:12:17,210 --> 00:12:20,700 notice that this goroutine here is in the select. 277 00:12:20,700 --> 00:12:23,490 Remember the select lets us manage 278 00:12:23,490 --> 00:12:27,140 multiple channel operations, sends and receives, 279 00:12:27,140 --> 00:12:28,140 at the same time. 280 00:12:28,140 --> 00:12:29,980 And if you look in the first case, 281 00:12:29,980 --> 00:12:34,820 we're now sitting in a receive, right? 282 00:12:34,820 --> 00:12:36,680 We're in a receive right here, 283 00:12:36,680 --> 00:12:40,020 for the data that we're trying to get back 284 00:12:40,020 --> 00:12:41,030 from this goroutine. 285 00:12:41,030 --> 00:12:42,700 We're in the channel receive. 286 00:12:42,700 --> 00:12:44,250 This is that send on the channel, 287 00:12:44,250 --> 00:12:46,140 this is the receive on the channel. 288 00:12:46,140 --> 00:12:48,080 Ideally this is what we want. 289 00:12:48,080 --> 00:12:52,130 We want this send right here, and this receive, 290 00:12:52,130 --> 00:12:53,570 to come together. 291 00:12:53,570 --> 00:12:57,040 We want the send and the receive to come together. 292 00:12:57,040 --> 00:12:58,780 That's our send, the work is done. 293 00:12:58,780 --> 00:13:00,180 This is our receive. 294 00:13:00,180 --> 00:13:01,770 We want that to happen but, 295 00:13:01,770 --> 00:13:03,640 at the same time we're waiting for that, 296 00:13:03,640 --> 00:13:05,940 line 46 is very important. 297 00:13:05,940 --> 00:13:09,560 Notice that we're also on a receive, 298 00:13:09,560 --> 00:13:13,000 we're on a receive also for, 299 00:13:13,000 --> 00:13:16,440 the done function on the context. 300 00:13:16,440 --> 00:13:19,140 So what we're looking at here is this function, 301 00:13:19,140 --> 00:13:22,853 this context, has a method called done. 302 00:13:23,700 --> 00:13:26,050 And we're also going to report here on done. 303 00:13:26,050 --> 00:13:27,500 We're gonna say okay, 304 00:13:27,500 --> 00:13:31,560 if the done function returns before the channel receive 305 00:13:31,560 --> 00:13:33,910 on line 43, hey guess what? 306 00:13:33,910 --> 00:13:35,120 We've timed out. 307 00:13:35,120 --> 00:13:37,570 So basically the Context package is doing this. 308 00:13:37,570 --> 00:13:38,760 It's now sitting, 309 00:13:38,760 --> 00:13:41,670 we get into the select, we're now sitting in this timer, 310 00:13:41,670 --> 00:13:43,270 we're on this call to done. 311 00:13:43,270 --> 00:13:45,220 Once we call done, we're now saying, 312 00:13:45,220 --> 00:13:48,083 we're gonna wait 150 milliseconds, 313 00:13:49,110 --> 00:13:54,110 and if in 150 milliseconds you're not out of this done call, 314 00:13:54,660 --> 00:13:58,480 then we're going to move on. 315 00:13:58,480 --> 00:14:01,990 So at the time we call done, that clock is going to start, 316 00:14:01,990 --> 00:14:04,130 and we're saying we're gonna wait here for 150 milliseconds 317 00:14:04,130 --> 00:14:05,320 and if it doesn't, 318 00:14:05,320 --> 00:14:08,700 then we're gonna send on that receive right there, 319 00:14:08,700 --> 00:14:09,700 we're gonna do the send. 320 00:14:09,700 --> 00:14:12,350 We're going to now be able to move on. 321 00:14:12,350 --> 00:14:16,540 We are hoping however, that this work gets done faster. 322 00:14:16,540 --> 00:14:19,760 Now we've already guaranteed that in this code here, 323 00:14:19,760 --> 00:14:22,450 so if we come over and run this program, 324 00:14:22,450 --> 00:14:23,900 what you're gonna see, 325 00:14:23,900 --> 00:14:26,140 change directory, go build. 326 00:14:26,140 --> 00:14:29,730 What you're gonna see is that the work got completed. 327 00:14:29,730 --> 00:14:31,170 So what happened? 328 00:14:31,170 --> 00:14:33,560 Well we sat in the select case, 329 00:14:33,560 --> 00:14:37,120 either the work gets completed, or we timeout. 330 00:14:37,120 --> 00:14:39,420 Since this was only 50 milliseconds, 331 00:14:39,420 --> 00:14:41,760 we were able to perform this channel send, 332 00:14:41,760 --> 00:14:44,370 with this receive, work completed. 333 00:14:44,370 --> 00:14:47,400 But what if we turn this into five seconds? 334 00:14:47,400 --> 00:14:49,810 What if it's five seconds? 335 00:14:49,810 --> 00:14:50,920 Now we run it. 336 00:14:50,920 --> 00:14:53,430 Look what it says, work canceled. 337 00:14:53,430 --> 00:14:56,280 So we now went to five seconds, what happened? 338 00:14:56,280 --> 00:14:59,060 This goroutine is there, this now, 339 00:14:59,060 --> 00:15:02,510 the done call started a 150 millisecond wait. 340 00:15:02,510 --> 00:15:06,620 150 milliseconds passed, we now received our miss channel, 341 00:15:06,620 --> 00:15:08,670 the done returns a channel, 342 00:15:08,670 --> 00:15:12,410 that's why you see the receive is directly on the done call. 343 00:15:12,410 --> 00:15:15,890 You can see it returns a receive-only channel, 344 00:15:15,890 --> 00:15:20,890 and now we report that this is done and we move on. 345 00:15:20,990 --> 00:15:25,250 Eventually this work finishes, the send has to happen, 346 00:15:25,250 --> 00:15:27,720 or we leak a goroutine and we're back to the ID 347 00:15:27,720 --> 00:15:30,040 of that buffer channel of one. 348 00:15:30,040 --> 00:15:33,020 So this is our cancellation pattern okay? 349 00:15:33,020 --> 00:15:35,130 This is how we do deadlines and timeouts. 350 00:15:35,130 --> 00:15:38,460 A deadline is when you don't give it a duration, 351 00:15:38,460 --> 00:15:41,720 but you give it an actual moment in time 352 00:15:41,720 --> 00:15:43,120 that you want things to happen. 353 00:15:43,120 --> 00:15:46,940 We tend, I tend to use duration-based timeouts much more 354 00:15:48,807 --> 00:15:50,780 than I use the deadline-based timeouts. 355 00:15:50,780 --> 00:15:54,470 But it's all gonna be the same thing okay? 356 00:15:54,470 --> 00:15:57,400 We're gonna be waiting for the goroutine to finish its work, 357 00:15:57,400 --> 00:16:02,210 or we're gonna give it, in this case, 150 milliseconds 358 00:16:02,210 --> 00:16:03,470 to finish the work. 359 00:16:03,470 --> 00:16:06,630 If 150 milliseconds hits, boom, cancellation, 360 00:16:06,630 --> 00:16:07,670 we move on. 361 00:16:07,670 --> 00:16:10,840 And if not then we're gonna get the data 362 00:16:10,840 --> 00:16:14,070 and life is super good. 363 00:16:14,070 --> 00:16:16,810 So this is our base use of the Context package 364 00:16:16,810 --> 00:16:20,640 both for storing values and for dealing 365 00:16:20,640 --> 00:16:22,423 with cancellation and timeout.