Golang Channels Or Wait Groups? Let Me Explain.

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
when should we use channels and when should you use weight groups is a question that recently came up in my Discord community and by the way if you're not yet inside of that beautiful Community with over I think already 4,000 people uh basically learning from each other each and every single day 24/7 you should basically do it right now the link is in the description also if you're not yet subscribed to my channel consider subscribing um give me a thumbs up and leave some questions in the comment I love you much appreciated by the way guys Black Friday is coming up and I'm giving away 20 seats with 60% off for the fulltime goe program it's a program where we're going to cover the introduction to goang we are going to cover mastering concurrency um we are building a Json API backend hotel reservation API back end we are building microservices um from scratch and with the go kit I'm covering how to land a job and we also have this bonus my treat to you is mastering core blockchain development U all inside of the program 60% off for the first 20 seats when should we use channels and when should we use weight groups so basically weight group is a way for synchronizing and a channel is a way for communication although you could say yeah but we can also use channels for synchronization that's true but weight groups are basically a very easy and convenient way to quickly synchronize go routines or whatever you want to have synchronized so let's take uh a closer look here with an example so for example I'm going to make here a function do work or something I don't know do work we're going to give this a d it's going to be a time duration right and we're going to say he fmt um doing work right boom boom boom just like that we're going to do a Time sleep of D and then we're going to copy this fmt statement here and we're going to say say um work is done something like that yes that should be good so basically um yeah so let's say we going to have do work uh time second times two and we going to copy this do work function again and we're going to save four seconds right so let's say you have two functions here right and let's actually do something like uh a start going to be a time now and then we could do something like fmt print L print F print F and I'm we going to say um work took percentage F new line uh seconds maybe and then we're going to put the time since start in here right so if we run that right so it's doing work the work is done it's doing work again and then it's basically going to complete and it's going to tell us that the work took six seconds well why 6 seconds very easy quick math 2 seconds plus 4 seconds is 6 seconds yes that's completely true so basically uh in goang we have a very easy way to schedule functions into another go routine which basically means we can actually uh it's not actually theoretically true what I'm going to say but we can run these functions at the same time but they that with a green assault right but hey something like that right so why are we uh um why should we do that well basically if we can run these two function if we can schedule these two functions at the same time it basically means we only need to wait for the weakest link right and what is the weakest link it's basically the four seconds that's basically what is going to take us the long the longest time right so how do we do that in go is very simple we could do prefix that with go prefix that with go super easy these two functions are basically scheduled in another go te right so what's going to happen if we run that well if we run that that the problem is the work took basically one millisecond nanc whatever is microsc I don't know even know what it is but that's because we basically schedule these two functions in under go routine but our program is accident so there's no way we're going to synchronize these goes with our main program so how do we do that well you can do it with channels but I think it's going to be a little that's just an over hat I think we can just use weight groups which is basically exactly why that thing is in the in the standard Library so how can we do that well we can do something like uh the OU is going to be a sync uh weight group right just like that and then we need to basically pass this weight group into these functions here right just like that you can make a global whatever uh so we don't need to pull into this function but doesn't really matter right so we're going to say that the W is going to be a sync weight group uh just like that and we're going to say here that each time the function is completed we're going to basically say we done right so we're going to basically tell the weight group like Hey listen the work is done easy peasy right so we need to give this basically by reference like that that's pretty fine so now we need to basically tell how many counters we need to increment for this weight group right so we we're going to say here V add and because we have two two times the work we need to done you could also call add into this uh do work function if you want so we're going to say w add2 why because we're going to have two functions two workers two worker functions let's say that are going to be scheduled so we're going to add two here we're going to spin up the work and then of course at the end we need to basically wait until these two functions are done right so that's exactly what we're going to do so let's run this function right so it's doing work at the same time so the two seconds is done then the four seconds is done but now we can see that we only needed to wait for the weakest link which is basically exactly 4 seconds right and there's not much things we needed to do right we just have uh we just added a weight group into our function and we communicate that we are done here and we add just two of these counters um and that's it right if you add three of these counters it's going to be a problem because if we run the function then right if you run the program then the problem is we're going to these workers are going to do their job but now it's going to say hey yo listen all gtins are asleep you have a deadlock why well because the program the compiler already knows that if these um worker functions basically call W done but there is still one increment right there's still one uh left but nobody's calling that just like your girlfriend nobody's calling that so basically um the program knows that the compiler is smart enough to know that and it's going to notify you with a panic like yo we have a deadlock please fix your code right so that's basically synchronization so why why are we using weight groups here because there is no such message that needs to be communicated right there is no such return value or something some result this function has that we need to use into some other logic right so but what if we what if do work is going to uh for example do work is going to return a string right a result right so um well then there is no way for us to communicate that with a weight group well that's where channels come into play so let's basically make a very simp simplified um example here so the first thing we're going to do is we're going to delete this weight group right because we don't need it and then we are going to uh we need to use channels so this return I'm going to make it wrong first so you know why so let's do return um that's a good question actually uh because it's going to be the same it's the same function how can we actually fix that um I'm going to do a string here so we actually have a different thing here for theb purposes right we're going to return s that's the thing uh close your eyes so basically we're going to delete this weight group you don't need it anymore go do work uh just like that work one we're going to call this work two right right no weight Loop here right so basically what's going to happen is that um what we put into this function we basically going to use that as the result so we actually can debug that right so en able to communicate this we need to have channels right so let's make a channel we're going to call this uh a rest Channel or make it result Channel which is going to be an channel of string right just like that so now we need to of or we make it a global or we just just put it into this function so let's do uh use it as an argument here so I'm going to say the Reas channel here what the is going on here we don't need that reel Channel Heat and the Reel Channel heat right um so then we can do something like I don't know rest one it's going to be um let's read from the channel here and then print it out to be honest rest one let's make it very simple guys this not it's just a very simple explanation so you can actually experiment with that and hopefully it gives you some more context on when are we going to use when is a good a good way to use um a good use case to use weight groups and when is a good use case to use channels right uh so don't take this uh too production ready stuff right some people are freaking out some people love it some people freaking out hey uh it's very hard to balance my my right so uh what's going on okay so now we have this s is going to be the string Y and now we're going to have this uh channel here so we're going to say Chan string right something like that and instead of returning right instead of returning because why we have this go here right there is no way for us to basically have a return value or we need to basically do a closure function but still a returning here is not is not the play right instead of returning we are going to delete the return statement here and we are going to use this rest Channel right and instead of returning we're going to say restal and we're going to put in string here right A lot of people are going to be confused Anthony why are you doing this s string here well it's basically because we have one function and you know maybe we should use a random thing actually to be honest that could be um yeah let's do that because it's going to confuse people I already know it's confusing me it's confusing me already so we're going to delete this thing so we only gonna have a rest Channel and then in order to do this we're going to do an fmt asint maybe asint F probably then we're going to say rent no uh work percentage D and now we going to say here uh rent in N uh 100 something like that right random number between 100 0 and 100 something like that yeah I'm happy I'm happy with this so we're going to do work put in the dies channel here um yeah something like that perfectly fine let's let's run it not sure if it's going to work let's see boom right so we're doing work at the same time but then we're going to see that we're going to have um work is done here and this is the result actually we're going to make it more clear for you guys here yeah yeah yeah that's what we're going to do um the result of the work and now we going to do like an add or something just like that right I turn it again G run main.go boom still early I'm sorry need to warm up so we're doing the work the work is done the result of the work is 40 uh 54 and the other work is done and the result is 30 and it took us 4 seconds right so that's basically how you can um use channels and able to communicate results that are basically uh being computed in some other go routine right of course a lot of people would say yeah but now you have two of these functions what what happens if we have three right let's say we have three here right with eight seconds that's actually too much six seconds for example uh then we need to do something like this right we need to copy the whole shebang here right something like this boom and then paste that in here rest three print rest three so you see it's a little bit tedious right so what you could do in this case is um use something like this right you're going to delete that all this we can actually Loop over the channel for the people that didn't know right we can say uh the result result is going to be uh what's going on each I'm thinking range it's range over the result Channel just like that right and then we can actually say uh fmt paral and we're going to print the result something like that right the problem is and you're going to see what's going to what's going to happen so we're going to do this it's doing the work and then it's basically going to Loop over all these results you can see what is happening 70 63 and then nine but then the problem is that we get an error all good routines are as sleep we have dead look right so why is that well that's because the compile is just too smart goling is just too smart guys so it's going to happen is that um we have a result channel here right and we have three functions that are basically doing work and are writing into this channel when they are done right so we are looping here the compiler knows that we going to loop three times but after three times nobody is going to actually send stuff into that channel so that basically means that this Loop here is never going to stop right it's going to keep looping just like my anxiety it never stops so en able to do that we need to do again some kind of a synchronization way right some some kind of a way to synchronize that so and then you can use uh a weight group again right so why should we use a weight group let's make this actually a global variable so we don't need to hassle again so I'm going to say V VG is going to be um uh pointed to a sync weight group right something like that sync weight group real quick like that then we can make this W it's going to be an sync we group like this let's do V at three or something right we have three functions here perfectly fine um let's spin this in a go routine just like that why do we need this in a gotin well because actually we don't need to do that well we need to do that doesn't really matter there a couple ways to solve this right because if we don't put this into a go routine there is no way we can actually um it's going to block so there's no way to close our Channel no way to basically do some other logic right and so what we're going to do is we're going to Ouiji wait here right and when we stop waiting for this actually we need to do fmt print um we're going to say that work actually we do it like that like this sounds good sounds good good so we're going to Ouiji wait and after we wait we're going to close the res channel right so if we close res Channel this Loop is going to basically stop and it's going to trigger this uh print statement and everything is beautifully cleaned up um like it should be yes so now the only thing we need to do basically is uh Ouiji D here called D each time uh this do work is basically completed yeah that should actually work I have no clue it's like basically just on the top of my head uh and that can cause some problems sometimes let's press enter let's see what's going on here so it's doing uh the job here and and and that's that so basically something that's basically a problem is why is it not um actually to be honest that I'm going to do it like this right so the thing is this is cleaned up for sure right this is cleaned up for sure but the problem is that let me do something like um the program actually exit faster than this so what we're going to do is en able to show you guys actually we can do that but what we're going to do is a Time sleep here of one second um just to show you actually time. second should be fine here right uh let's do it again let's see experimenting guys experimenting meanwhile I'm drinking my I'm sipping my coffee why not yeah so now it's working so you can see uh we basically have these um functions that basically return their work perfectly fine and then uh it's going to say the work took six seconds yes because um the weakest link is six seconds here right okay uh so why am I doing this stupid time sleep thingy well the thing is that if we close this channel the program is going to exit and if the program is exiting nothing can happen anymore right so the thing is that this will stop and it will print out this but the program exits before it can even print this stuff right that's that's what's happening so that's why I'm doing this uh cheats of uh time. sleep so we can actually wait one second so you're going to see that this is basically being triggered that this function is being cleaned up that we synchronized that all the work is done and that we don't need to Loop anymore right so that's basically it guys um like I said it's it's it's not like a prediction ready uh real case scenario but this should be a very very good example or a set of examples so you can experiment and it should actually um give you some some more context on when and why and how it all works a little bit more so if you want to learn more about channels because this is basically an unbuffered channel uh is uh an unbuffered Channel yeah if you want to learn more on when to use buffer unbuffered and all that stuff I have some other videos on my channel if you want to learn more about channels and and all that stuff in depth the links are in the description thanks for watching and I see you in the next video or live stream peace
Info
Channel: Anthony GG
Views: 18,893
Rating: undefined out of 5
Keywords: golang, go, golang channels, golang waitgroups, go async, golang waitgroup, learn golang, concurrency, golang tutorial, golang for beginners, golang concurrency, concurrency in golang, golang tutorial for beginners, goroutine, goroutines, go concurrency, goroutines in golang, golang goroutines, golang sync package, golang goroutine, go programming tutorial, go programming language, learn go, goroutines and channels in golang, programming, software engineering, vscode
Id: 2B-VAxCmhgA
Channel Id: undefined
Length: 18min 32sec (1112 seconds)
Published: Tue Nov 21 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.