I am so confused by goroutines.
Here is the code
func main() {
// runtime.GOMAXPROCS(1)
go spinner(100 * time.Millisecond)
const n = 45
fibN := fib(n) // slow
fmt.Printf("\rFibonacci(%d) = %d\n", n, fibN)
}
func spinner(delay time.Duration) {
for {
for _, r := range `-\|/` {
fmt.Printf("\r%c", r)
time.Sleep(delay)
}
}
}
func fib(x int) int {
if x < 2 {
return x
}
return fib(x-1) + fib(x-2)
}
That is a simple goroutine tutorial code which using goroutine to show an ASCII animation when calculating Fibonacci.
When I set GOMAXPROCS
to 1
, I think that there will be only one thread to execute goroutine and the Fibonacci function doesn't have any point to yield to animation goroutine. But this demo still works. It shows animation while doing calculating.
How does Go do this without goroutine switching?
Among others : the compiler inserts potential switch points at each function call, so each recursive call to fib(...)
can yield to the "spinner" goroutine.
If you try to implement fib without any function call for example :
// note : this is a truly horrific way to compute the Fibonacci sequence,
// don't do this at home
// simulate the "compute Fibonacci recursively" algorithm,
// but without any function call
func fib(n int) int {
var res = 0
var stack []int
stack = append(stack, n)
for len(stack) > 0 {
// pop :
n = stack[len(stack)-1]
stack = stack[0 : len(stack)-1]
if n < 2 {
res += n
continue
}
// else : push 'n-1' and 'n-2' on the stack
stack = append(stack, n-1, n-2)
}
return res
}
https://play.golang.org/p/pdoAaBwyscr
you should see your spinner 'stuck'