WEBVTT 00:00.540 --> 00:07.620 This is the fifth video of this section channels in the previous video we looked at new taxes in this 00:07.620 --> 00:11.830 video well first understand how channels work and how we could use it. 00:11.850 --> 00:14.980 We'll look at Buffer channels and directional channels. 00:15.030 --> 00:20.730 We'll also see how to use the select statement for this will make a small app that will send two messages 00:20.730 --> 00:24.020 to the same go routine which will print them an exit. 00:24.060 --> 00:29.460 If it doesn't receive anything else in five seconds channels are the second primitive and the language 00:29.490 --> 00:32.040 allows us to write concurrent applications. 00:32.040 --> 00:36.420 We've talked a bit about channels in the communicating sequential processes section. 00:36.420 --> 00:39.340 Channels are the way we communicate between processes. 00:39.450 --> 00:45.030 We could be sharing a memory location and using me taxes to control the processes access but channels 00:45.030 --> 00:48.480 provide us with a more natural way to handle concurrent applications. 00:48.480 --> 00:54.030 That also produces better concurrent designs in our programs working with many go routines. 00:54.030 --> 00:55.300 Seems pretty difficult. 00:55.300 --> 00:57.890 We can't create some synchronization between them. 00:58.020 --> 01:03.120 The order of execution could be irrelevant as soon as they are synchronized channels are the second 01:03.120 --> 01:05.190 key feature to write concurrent applications in. 01:05.180 --> 01:11.970 Go a TV channel in real life is something that connects an emission from a studio to millions of TV's 01:12.390 --> 01:19.260 which acts as the receivers channels in go work in a similar fashion one or more go routines can work 01:19.260 --> 01:23.550 as emitters and one or more guy routine can act as receivers. 01:23.550 --> 01:29.890 One morphing channels by default block the execution of Go routines till something is received it's 01:29.890 --> 01:35.410 as if our favorite TV show delays the emission until we turn the TV on so we don't miss anything. 01:36.550 --> 01:38.110 How is this done in go. 01:38.140 --> 01:44.910 Let's see this open the main door go file and add our main function to create channels in go. 01:44.910 --> 01:51.390 We use the same syntax that we use to create slices the make keyword is used to create a channel and 01:51.390 --> 01:58.080 we have to parse the keyword Chan am a type that the channel will transport in this case strings. 01:58.080 --> 02:01.280 With this we have a blocking channel with the name channel. 02:01.290 --> 02:05.680 Next we launch a go routine that sends the message Hello well to the channel. 02:05.700 --> 02:12.240 This is indicated by the intuitive arrow that shows the flow the hello world text going to a channel. 02:12.240 --> 02:17.520 This works like an assignment in a variable so we can only pass something to a channel by first writing 02:17.520 --> 02:21.920 the channel then the arrow and find its value to pass. 02:21.960 --> 02:27.280 We cannot write Hello world followed by the intuitive arrows and then channel in this way. 02:27.630 --> 02:33.420 As we mentioned earlier this channel is blocking the execution of Go routines and send a message received. 02:33.420 --> 02:38.550 In this case the execution of the main function is stopped until a message from the launch to go routines 02:38.910 --> 02:44.680 reaches the other end of the channel in the line message code on equals intuitive arrow channel. 02:44.900 --> 02:49.610 In this case the arrow points in the same direction but it is placed before the channel indicating the 02:49.610 --> 02:54.460 data is being extracted from the channel and assigned to a new variable called message. 02:54.650 --> 02:58.140 Using the new assignment operator the AI's colon equals. 02:58.400 --> 03:02.480 In this case we don't need to use a weight group to synchronize the main function with the created go 03:02.480 --> 03:06.550 routines as a default nature of channels is to block until data is received. 03:06.710 --> 03:08.960 But does it work the other way round. 03:08.960 --> 03:12.680 If there is no receiver when the go routine sends a message does it continue. 03:13.250 --> 03:19.340 Let's edit the example we wrote here to see this let me replace this with the modified code. 03:19.530 --> 03:20.610 Perfect. 03:20.640 --> 03:25.410 Now we're going to use a sleep function again in this case we print a message when they go routine is 03:25.410 --> 03:26.430 finished. 03:26.430 --> 03:28.600 The big difference is in the main function. 03:28.710 --> 03:32.070 Now we wait one second before we listen to the channel for data. 03:32.100 --> 03:38.760 It's time to save the file and run the program moved to the terminal and run the command go run main 03:38.760 --> 03:45.000 dot go the output can differ because again there is no arguments in the order of execution but now we 03:45.000 --> 03:48.190 can see that no message is printed until one second is passed. 03:48.390 --> 03:52.670 After the initial delay we start listening to the channel take the data and print it. 03:52.890 --> 03:58.450 So the emitter also has to wait for a cue from the other side of the channel to continue its execution. 03:58.480 --> 04:03.430 To recap channels our ways to communicate between go routines by sending data through one end and receiving 04:03.430 --> 04:08.290 at the other like a pipe in the default state and emit a go routine will block its execution until a 04:08.290 --> 04:10.420 receiver guy routine takes the data. 04:10.420 --> 04:14.530 The same goes for a receiver guy routine which will block until some emitter sends data through the 04:14.530 --> 04:14.980 channel. 04:15.070 --> 04:20.500 So you can have passive listeners waiting for data or passive emitters waiting for listeners. 04:20.500 --> 04:23.020 Now let's step ahead and learn about buffered channels. 04:23.030 --> 04:27.010 A buffer channel works in a similar way to default on buffer channels. 04:27.010 --> 04:30.270 You can also pass and take values from them by using the arrows. 04:30.370 --> 04:35.110 But unlike UN buffer channels senders don't need to wait until some guy routine picks the data that 04:35.110 --> 04:35.770 they are sending. 04:36.130 --> 04:40.610 Let's open our main door go file and add the main function. 04:40.710 --> 04:45.840 Now this example is like the first example we use for channels but now we've set the capacity of the 04:45.840 --> 04:48.110 channel to 1 in the make statement. 04:48.180 --> 04:53.200 With this we tell the compiler this channel has a capacity of one string before getting blocked. 04:53.310 --> 04:59.450 So the first string doesn't block the emitter but the second would let's run this example First save 04:59.460 --> 05:06.180 the file and navigate to the terminal execute the command go run main dot go. 05:06.290 --> 05:09.260 Now we can run this small program as many times as we want. 05:09.410 --> 05:11.720 The output would always be in the same order. 05:11.720 --> 05:15.140 This time we've launched the concurrent function and waited for one second. 05:15.140 --> 05:19.790 Previously the anonymous function wouldn't continue until the second it passed and someone can pick 05:19.790 --> 05:21.380 the sent data. 05:21.470 --> 05:25.870 In this case with a buffer channel the data is held in the channel or freeze the go routine to continuous 05:25.880 --> 05:27.080 execution. 05:27.110 --> 05:32.780 In this case the go routine is always finishing before the White time passes this new channel has a 05:32.780 --> 05:39.360 size of 1 so a second message would block the go routine execution let's go back to the coat file and 05:39.360 --> 05:44.550 make the changes modify the code by adding malign second channel to the go function 05:47.640 --> 05:48.750 after the modifications. 05:48.750 --> 05:55.080 Make sure you make the changes here we add a second hello well to message and we provide it with an 05:55.080 --> 06:02.500 index now close the file and get back to the terminal to check the output execute the previous command 06:02.500 --> 06:03.110 again. 06:03.370 --> 06:04.110 And here's the output. 06:04.120 --> 06:08.670 Hello World 1 indicating that we've just taken one message from the channel buffer. 06:08.740 --> 06:13.690 We've printed it and the main function finished for the launch to go routine could finish the go routine 06:13.690 --> 06:17.710 got blocked when sending the second message and couldn't continue until the other end took the first 06:17.710 --> 06:18.290 message. 06:18.460 --> 06:22.330 Then it print so quickly that it doesn't have time to print the message to show the ending of the go 06:22.330 --> 06:23.050 routine. 06:23.110 --> 06:27.010 If you keep executing the program on the console sooner or later these scheduler will finish the go 06:27.010 --> 06:29.730 routine execution before the main thread. 06:29.740 --> 06:33.820 Now the next type of channels need to discuss are the directional channels. 06:33.820 --> 06:39.250 One call feature about go channels is that when we use them as parameters we can restrict their directionality 06:39.550 --> 06:42.690 so that they can only be used to send or to receive. 06:42.790 --> 06:46.620 The compiler will complain if a channel is used in the restricted direction. 06:46.810 --> 06:52.180 This feature applies a new level of static typing to go ups and makes code more understandable and more 06:52.180 --> 06:53.090 readable. 06:53.140 --> 06:58.480 We'll take a simple example with channels let us add the code for this to our main dot go file within 06:58.480 --> 07:04.740 the directional channel folder and here's the code which we'll be using for this example the line where 07:04.740 --> 07:11.650 we launched the new go routine that is go func H an intuitive arrow string states that the channel pass 07:11.650 --> 07:15.840 to this function can only be used as an input channel and you can't listen to it. 07:15.900 --> 07:22.880 We can also pass a channel that will be used as receiver channel only let's have the code for this as 07:22.880 --> 07:27.920 you can see the arrow is on the opposite side of the keyword channel indicating and extracting operation 07:27.920 --> 07:29.360 from the channel. 07:29.390 --> 07:34.190 Keep in mind that the channel arrow always points left to indicate a receiving channel. 07:34.190 --> 07:39.190 It must go on the left and to indicate and inserting channel it must go on the right. 07:39.260 --> 07:43.370 If we tried to send a value through this receive only channel the compiler will complain about it. 07:44.280 --> 07:52.960 Let's try this at the line c h followed by intuitive arrow and in double quotes Hello this function 07:52.960 --> 07:57.820 has a receive only channel that we will try to use to send the message Hello through. 07:57.820 --> 08:04.600 Let's see what the compiler says Save the file and move to the terminal execute the program. 08:04.700 --> 08:06.950 It doesn't like it and asks us to correct it. 08:07.130 --> 08:11.480 Now the code is even more readable and safe and we've just placed an arrow in front or behind the channel 08:11.480 --> 08:12.560 argument. 08:12.560 --> 08:17.920 Now let's have a look at the select statement the select statement is also a key feature and go. 08:17.940 --> 08:21.500 It's used to handle more than one channel input within a go routine. 08:21.500 --> 08:25.640 In fact it opens lots of possibilities in these select structure. 08:25.640 --> 08:29.650 We asked for program to choose between one or more channels to receive that data. 08:29.660 --> 08:34.790 We can say this data in a variable and make something with it before finishing the select the select 08:34.790 --> 08:36.920 structure is just executed once. 08:37.070 --> 08:41.540 It doesn't matter if it is listening to more channels it will be executed only once and the code will 08:41.540 --> 08:43.100 continue executing. 08:43.100 --> 08:48.650 If we wanted to handle the same channels more than once we have to put in a for loop we'll make a small 08:48.650 --> 08:54.530 app that will send messages hello and the message goodbye to the same go routine it will print them 08:55.070 --> 08:56.030 and exit. 08:56.030 --> 09:00.560 If it doesn't receive anything else in five seconds this diagram gives a clear picture of how our app 09:00.590 --> 09:02.080 work. 09:02.090 --> 09:07.460 Now let's move back to our main dot go file and here will first make a generic function that sends a 09:07.460 --> 09:12.640 string over a channel let's out the code for this. 09:12.670 --> 09:17.420 Now we can send a string over a channel by simply calling the send string method. 09:17.550 --> 09:18.950 It's time for the receiver. 09:19.080 --> 09:21.540 The receiver will take messages from both channels. 09:21.680 --> 09:26.190 The one that sends hello messages and the one that sends goodbye messages. 09:26.190 --> 09:28.800 This is what you saw in the previous diagram. 09:28.830 --> 09:35.450 Next we had the code for the receiver function let's start with the arguments. 09:35.660 --> 09:39.170 This function takes three channels to receiving channels. 09:39.170 --> 09:40.780 I want to send something through it. 09:41.540 --> 09:45.110 Then it starts an infinite loop with the four keyword. 09:45.200 --> 09:50.710 This way we can keep listening to both channels forever inside the scope of select block. 09:50.780 --> 09:54.130 We have to use a case for each channel we want to handle. 09:54.140 --> 09:57.150 Have you realized how similar it is to the switch statement. 09:57.200 --> 09:59.440 Let's see the three cases step by step. 09:59.540 --> 10:06.190 The first case takes incoming data from the hello CHF argument and saves it in a variable called message. 10:06.230 --> 10:08.560 Then it prints the contents of this variable. 10:08.690 --> 10:13.760 The second case takes the incoming data from the goodbye c h arguments and saves in a variable called 10:13.760 --> 10:15.020 Message 2. 10:15.050 --> 10:17.840 Then it also prints the contents of this variable. 10:17.840 --> 10:19.690 The third case is quite interesting. 10:19.730 --> 10:21.860 It calls a time function. 10:21.860 --> 10:26.900 After that if we check its signature it accepts a time and duration value and returns are receiving 10:26.900 --> 10:32.780 channel dates receiving channel will receive a time the value of time after the specified duration is 10:32.780 --> 10:33.940 passed. 10:33.950 --> 10:39.980 In our example we use the channel it returns as a timeout because to select restarted after each handle 10:40.460 --> 10:42.700 the timer is restarted too. 10:42.710 --> 10:48.800 This is a very simple way to set a time or two ago routine waiting for the response of one or many channels. 10:48.800 --> 10:52.980 Everything is ready for the main function so let's add our main function 10:55.750 --> 10:57.040 again step by step. 10:57.040 --> 11:00.290 We created the three channels that will need in this exercise. 11:00.340 --> 11:03.870 Then we launched our receiver function in a different routine. 11:03.940 --> 11:08.110 This go routine is handled by go's scheduler and our program continues. 11:08.110 --> 11:12.670 We launched a new go routine to send the message Hello to the hello CHF arguments. 11:12.790 --> 11:17.980 Again this is going to occur eventually when the go scheduler decides our program continues again and 11:17.980 --> 11:19.130 waits for a second. 11:19.210 --> 11:24.850 In this break go scheduler will have time to execute the receiver and the first message if it hasn't 11:24.850 --> 11:25.560 done so yet. 11:25.570 --> 11:29.200 The Hello message will appear on the console during the break. 11:29.200 --> 11:34.330 A new message is sent over the goodbye channel with the goodbye text in a new go routine and our program 11:34.330 --> 11:39.850 continues again to a line where we wait for an incoming message in the quit C argument we've launched 11:39.850 --> 11:41.390 three go routines already. 11:41.500 --> 11:46.360 The receiver that is still running the first message and had finished when the message was handled by 11:46.360 --> 11:51.770 the select statement and the second message was printed almost immediately and had finished too. 11:51.850 --> 11:56.560 So just the receiver is running at this moment and if it doesn't receive any other message in the following 11:56.560 --> 12:01.450 two seconds it will handle the incoming message from the time structure after Channel type. 12:01.450 --> 12:07.210 Print a message to say that it is quitting in the true to the quit C H and break the infinite loop where 12:07.210 --> 12:17.600 it was looping save the file and let us run the small lab execute the command go run main dot go now. 12:17.760 --> 12:21.020 The result may not be very impressive but the concept is clear. 12:21.360 --> 12:28.200 We can handle many incoming channels in the same go routine by using the select statement superb The 12:28.200 --> 12:35.100 last feature about channels that we'll see is ranging over channels we're talking about the range keyword. 12:35.370 --> 12:41.940 We've used it extensively to range over lists and we can use it to range over a channel to open the 12:41.940 --> 12:46.630 main don't go file and add the main function now. 12:46.720 --> 12:52.350 In this case we've created an unbundled channel but it would work with a buffered one too. 12:52.540 --> 12:57.390 We launched our function in the new go routine that sends the number one over a channel. 12:57.400 --> 13:04.100 Wait a second sends a number two and closes the channel the last step is to range over the channel. 13:04.150 --> 13:06.700 The syntax is quite similar to a list range. 13:06.820 --> 13:12.790 We store the incoming data from the channel in the variable v and we print this variable to the console. 13:12.790 --> 13:15.630 The range keeps iterating until the channel is closed. 13:15.670 --> 13:20.480 Taking data from the channel can you guess the output mister or program. 13:20.500 --> 13:27.450 Don't worry I'll run and show it to you right now Let's navigate to a terminal and execute the RUN command. 13:30.190 --> 13:31.780 Again not very impressive. 13:31.780 --> 13:33.220 It prints the number 1. 13:33.340 --> 13:34.660 Then wait a second. 13:34.660 --> 13:40.270 Prints in number 2 and exits the application according to the design of this concurrent app. 13:40.270 --> 13:45.430 The range was iterated over possible incoming data from the channel until the concurrent go routine 13:45.430 --> 13:46.900 closes the channel. 13:46.900 --> 13:50.110 At that moment the range finishes and the app connects it. 13:50.340 --> 13:55.570 Range is very useful in taking data from a channel and it is commonly used in fan patterns where many 13:55.570 --> 13:58.520 different go routine send data to the same channel. 13:58.650 --> 14:04.780 Cool in this video we've learned about channels in go in the next video we'll write a concurrent counter 14:05.470 --> 14:06.940 like the one we wrote in New Texas.