► Join my Discord community for free education 👉 discord.com/invite/bDy8t4b3Rz ► Become a Patreon for exclusive tutorials👉 www.patreon.com/anthonygg_ Thanks for watching
Great video that helped my a lot make sense. At times - you seem to be running too hot trying to explain/do too much but at end I understood everything.
Great. I'm learning Go and using channels, go routines and waitgroups to read and check information from multiple files. I'm using select and a quit channel to control the end of processing.
This serves as a good example of aggregating data but a lot of the time you are connecting to an external data source which can throw errors on your method calls, hope in the future if you re visit this you show
In this case, you're right. But it's only viable if the number is static (in this example, the size of the buffer is 2). We would've had a different case if it was an unbuffered channel.
Great videos, thank you for them! I have a question: How come the channel itself is being passed around to various functions, and not the pointer to the channel? Wouldn't we need a pointer to the channel, so that the data is persistent once all the go routines complete? I guess I am missing something.
Hi , great explanation . Question : in this example when ranging over respch how do you know 1st item will be like or the match ? Is it random or in order of function calls ?
Usually it depends, whichever function writes to the channel first. If you fetch from a remote resource you don't know what value will be written to the channel first because you don't know the latency, but in this case you know the name will come first since the function sleeps 100 ms and then writes to the channel while the likes function sleeps for 150 and then writes. The order of the function call does not matter since they are concurrent. Hope i was clear :)
@@marinm3869 Yes you are right. But what would happen in the case of an API calls? I would never know how much time it would take. Then how will I know which API call am I reading from the channel. How are we supposed to differentiate the values from the channel?
Wait group is one way to solve this. Another is to just iterate over the number of tasks (2) and receive from the channel. No need to close, it will get GC'ed as usually.
The waitgroup is used so we know when to close the channel. When I think about it, your approach could also work. But I thought showcasing "ranging over channels" and "sync.Waitgroup" was important.
Question:- what if my go routine is sending data and i want to manipulate the same in main function . This seems to be sync behavior as we are collecting response in channel and then closing it and later we are manipulating the same. Can you suggest some approach how it can be done in my scenario as it keeps throwing error. Thanks in Advance.
it is just a demo, you probably don't want to mix the response type with a generic one like any, or you actually can mix it by embracing the usage of a generic type
@@anthonygg_ hey mate that wont work... we havent assigned a key:value pair to each of those go routines. tried using make(chan map[string]any, 2) but seems very messy :/
@@anthonygg_ i created a struct respch := make(chan UserStuff, 2) and then in the funcs i used UserStuff{key: "likes", value: 11} and UserStuff{key: "match", value: "ANNA"} which appears to work ok... not sure if there is a cleaner approach.
@@rogerramjet69 I think that's a way cleaner approach to be honest, I thought any was really suss. I would create two structs however, `userLikes{likes: int, error: err}` and `userMatch{match: str, error:err}`. This pattern is more intentional and also lets you check for errors.
Uhhh you only called two functions with the go routine's and the runtime was the SUM of both of them. You didn't solve the problem you wanted; combing their runtime so the max total was the worst single.
actually the 250 ms is the sum of first non goroutine function fetchUser() which takes a 100 ms and then the worse of the two functions that are goroutines, so max(150,100) which in total gives us 250. Initially without goroutines, the sum was 350 ms
► Join my Discord community for free education 👉 discord.com/invite/bDy8t4b3Rz
► Become a Patreon for exclusive tutorials👉 www.patreon.com/anthonygg_
Thanks for watching
That subtle GF joke totally sent me 🤣🤣You said it without flinching too. Thank you for this , its actually really helpful
🙏
thanks, I have struggled a bit to understand the whole concept of goroutines, channels and wait groups, but this cleared all doubts.
This is the best example on Golang concurrency I could ever come across. Period.
Great video that helped my a lot make sense. At times - you seem to be running too hot trying to explain/do too much but at end I understood everything.
Great. I'm learning Go and using channels, go routines and waitgroups to read and check information from multiple files.
I'm using select and a quit channel to control the end of processing.
what could be a good match for Bob? Alice! goddamn Alice!!!
i really enjoy how you tell something with some jokes, thank you 🤣
This serves as a good example of aggregating data but a lot of the time you are connecting to an external data source which can throw errors on your method calls, hope in the future if you re visit this you show
Or you could just do `resp := make(any, 2); for i := range resp { resp[i] =
True! Thanks for this.
@kke can you explain how this works:) ?
@kke thank you for this tip!
In this case, you're right. But it's only viable if the number is static (in this example, the size of the buffer is 2). We would've had a different case if it was an unbuffered channel.
Amazing Explanation!!
Awesome video, Thanks. Must say that all other videos on goroutines on YT are useless except for yours.
Quality videos for the fans!
Good job man 😊
Great videos, thank you for them!
I have a question: How come the channel itself is being passed around to various functions, and not the pointer to the channel? Wouldn't we need a pointer to the channel, so that the data is persistent once all the go routines complete? I guess I am missing something.
Channels are syntactic sugar. Thats all being handled by the compiler.
Thanks finally i understand it :)
Excellent explanation!! Thank you
Great explanation. Thanks!
Awesome video. Thanks!
Hi , great explanation . Question : in this example when ranging over respch how do you know 1st item will be like or the match ? Is it random or in order of function calls ?
same question
Usually it depends, whichever function writes to the channel first. If you fetch from a remote resource you don't know what value will be written to the channel first because you don't know the latency, but in this case you know the name will come first since the function sleeps 100 ms and then writes to the channel while the likes function sleeps for 150 and then writes. The order of the function call does not matter since they are concurrent. Hope i was clear :)
@@marinm3869 Yes you are right. But what would happen in the case of an API calls? I would never know how much time it would take. Then how will I know which API call am I reading from the channel. How are we supposed to differentiate the values from the channel?
its very informative video indeed. thank you sir
Love your accent man, where u come from? Sounds a wee bit Dutch but also not😂
thanks for sharing !!
love this channel
Perfectly ❤
Wait group is one way to solve this. Another is to just iterate over the number of tasks (2) and receive from the channel. No need to close, it will get GC'ed as usually.
If we know for how many routines we have to wait, why not use regular indexed for loop?
what is the benefit of using the wait group?
for i:= 0; i
The waitgroup is used so we know when to close the channel. When I think about it, your approach could also work. But I thought showcasing "ranging over channels" and "sync.Waitgroup" was important.
Question:- what if my go routine is sending data and i want to manipulate the same in main function . This seems to be sync behavior as we are collecting response in channel and then closing it and later we are manipulating the same. Can you suggest some approach how it can be done in my scenario as it keeps throwing error. Thanks in Advance.
If we are querying from DB, I don't think goroutine would be much helpful since its an I/O operation.
Third party api
@@anthonygg_ I don't get it?
What if we need to zip responses from 2 different channels.
Hi Anthony, very love your golang video. But i still don't known when we should use gorountine and handle gorountine correctly, can u help me
is it good practice to emit to same channel despite multiple different api calls?
it is just a demo, you probably don't want to mix the response type with a generic one like any, or you actually can mix it by embracing the usage of a generic type
Thats a good example maybe with real database con reall and some call api too
Understood everything except the part of GF what is a GF it's a Type or library??
Girlfriend
@@anthonygg_you missed the joke damn
i still dont understand how to handle if function userLikes returns string and error (not only 1 return)
I dunno either, but maybe a user defined struct of response and error? Make the chan of that type?
how do you specify a key from the channel... say in the loop I just want to print likes...something like if respch.key == 'likes' print blah
for key := range channel. So your that will be the key you are looking for.
@@anthonygg_ hey mate that wont work... we havent assigned a key:value pair to each of those go routines. tried using make(chan map[string]any, 2) but seems very messy :/
@@anthonygg_ i created a struct respch := make(chan UserStuff, 2) and then in the funcs i used UserStuff{key: "likes", value: 11} and UserStuff{key: "match", value: "ANNA"} which appears to work ok... not sure if there is a cleaner approach.
@@rogerramjet69 You should be good. If you want to discus this more in-depth you maybe join my Discord community. That chats a bit better.
@@rogerramjet69 I think that's a way cleaner approach to be honest, I thought any was really suss. I would create two structs however, `userLikes{likes: int, error: err}` and `userMatch{match: str, error:err}`. This pattern is more intentional and also lets you check for errors.
Typing that fast!
"it waiting but it never comes... just like your gf". ☠
🤙🤙🤙
🤙🤙🤙🙏🏽🧐
Uhhh you only called two functions with the go routine's and the runtime was the SUM of both of them. You didn't solve the problem you wanted; combing their runtime so the max total was the worst single.
actually the 250 ms is the sum of first non goroutine function fetchUser() which takes a 100 ms and then the worse of the two functions that are goroutines, so max(150,100) which in total gives us 250. Initially without goroutines, the sum was 350 ms
Check the third fucn which takes 100s i believe that solves your problem
so this is equivalent to Promise.all in JS?
I have same opinion