In Ireland we drive on the left and yield right of way for on comming traffic, forget to yeild and it’s a big mess.
Goroutines in Go also require you to yeild, forget and you also have a big mess.
The Go runtime manages threads/goroutiens in you application. So when you use ‘go’ to create a goroutine the Go runtime will created thread/goroutine. This thread/goroutine is not created on or by the operating system. The Go runtime will map it’s threads/goroutines to operating system threads and schedule the for a slice of time to run.
This is why it is low cost to create and use goroutiens as they are not operating system threads. Operating system threads have to allocate memory space on the stack to hold the info during a contex switch, this is expensive, also to create a thread a system call has to be preformed, this is also expensive. One other thing here is the fact that operating system threads are preemptive, the operating system halts and saves the contex and then passes the CPU to another thread/process for it to run.
Go uses a cooperative threading model, this means that your code has to yeild so the Go runtime can give the CPU/operating thread to other goroutines to run. If your app dose no yeild then other goroutines in that application do not get time to run.
Just imagine having to write you code and pick points to yeild so other threads/goroutiens could run. Luckily Got has figured this out and for the most part when your code is blocked wating for something like a response from a socket you have yielded or if you are wating on a channel or have called sleep you have also yielded.
With how goroutine work in our minds we can better understand that a thight loop like a for or while loop that takes a long time to finish a task that dose not block is not good. Their is no chance for the runtime to get to schedule. You must ensure that you do not use thight loops or if you do that you provide a way for the runtime scheduler and do its job, you could just do a ‘ sleep’ now and again while in the thight loop. But it best to try to avoid thight loops completely.
So why has Go decided on this model, well its faster because their is no context switching. In large applications where their could be lots of threads the context switching will grind the operating system to a halt. With a go routiens their is no context switching, no system calls to create or clean up threads, way less memory overhead. All this means that goroutiens work very well for web scale applications.
For me I had to force my brain to think different when writing Go code. I always tryed to not use threads or if I did I would pool them. Now I can freely create and use goroutiens, this gives us a new way to develop.
One last thing that I see people doing with goroutines is creating them and providing no way to gracefully clean up. Many Go apps use the quick kill method to shutdown their application. Unless you know what your app is doing at that point in time you could loose data. It be better to provide a way to shutdown the goroutines gracefully.
I hope you find this useful, if you have questions please leave a comment.