
An OS thread uses a fixed amount of memory for its stack, and with an increase in the number of threads, the overhead of switching between them is high. This is the reason that creating a new thread for each request to a server isn't considered a good idea.
Goroutines are different though. They are initialised and scheduled by the Go runtime, and not visible to the OS at all. All the goroutines that are currently alive are multiplexed onto the few threads allocated by the OS to the program. The creation of a goroutine does not require much memory - only 8kB of stack space.
What happens when the stack runs out ?
The Go runtime handles scheduling of the goroutines. The goroutines are scheduled cooperatively, while threads are not.
This means that every time a thread switches, you need to save/restore ALL registers, that is, 16 general purpose registers, PC (Program Counter), SP (Stack Pointer), segment registers, 16 XMM registers, FP coprocessor state, X AVX registers, all MSRs etc.
When another goroutine is scheduled, only 3 registers need to be saved/restored - PC, SP and DX. [5] Both the Go scheduler and any modern OS scheduler are O(1) in complexity, meaning additional threads/goroutines do not increase switching time, but the overhead of changing register values do matter.
Not desirable in threads since you don't have that many of them.
When a goroutine blocks it simply gives the oportynity of another goroutine to run.
You can set the number of cores used.
You can't set the number of threads created.
You can assign priority of the goroutines (although it isn't trivial)
The way goroutines should communicate.
Two types: Buffered and blocking
Initial control statements: Select and Range
A single channel can be shared between any number of threads.
The channels handle the locking and so on.
http://play.golang.org/p/yGTd4MtgD5
http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go