对于这个挑战,你需要通过提高现有程序的运行速度来改进它。 尝试自己编写程序,即使你不得不回头查看你以前用于练习的示例也要尝试。 然后,将你的解决方案与下一单元中的解决方案进行比较。
Go中的并发是一个复杂的问题,在实践中你会更好地理解它。 这一挑战只是你可以用来实践的一个建议。
祝好运!

利用并发方法更快地计算斐波纳契数

使用以下程序按顺序计算斐波纳契数:
package main

import (
    "fmt"
    "math/rand"
    "time"
)

func fib(number float64) float64 {
    x, y := 1.0, 1.0
    for i := 0; i < int(number); i++ {
        x, y = y, x+y
    }

    r := rand.Intn(3)
    time.Sleep(time.Duration(r) * time.Second)

    return x
}

func main() {
    start := time.Now()

    for i := 1; i < 15; i++ {
        n := fib(float64(i))
    fmt.Printf("Fib(%v): %v\n", i, n)
    }

    elapsed := time.Since(start)
    fmt.Printf("Done! It took %v seconds!\n", elapsed.Seconds())
}
你需要根据现有代码构建两个程序:
实现并发的改进版本。 完成此操作需要几秒钟的时间(不超过15秒),就像现在这样。 应使用有缓冲channel。
编写一个新版本以计算斐波纳契数,直到用户使用fmt.Scanf() 函数在终端中输入quit。 如果用户按Enter,则应计算新的斐波纳契数。 换句话说,你将不再有从1到10的循环。
使用两个无缓冲channel:一个用于计算斐波纳契数,另一个用于等待用户的"退出"消息。 你需要使用select语句。
下面是与程序进行交互的示例:
1

1

2

3

5

8

13
quit
Done calculating Fibonacci!
Done! It took 12.043196415 seconds!

实现并发并使程序的运行速度更快的改进版本如下所示:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func fib(number float64, ch chan string) {
    x, y := 1.0, 1.0
    for i := 0; i < int(number); i++ {
        x, y = y, x+y
    }

    r := rand.Intn(3)
    time.Sleep(time.Duration(r) * time.Second)

    ch <- fmt.Sprintf("Fib(%v): %v\n", number, x)
}

func main() {
    start := time.Now()

    size := 15
    ch := make(chan string, size)

    for i := 0; i < size; i++ {
        go fib(float64(i), ch)
    }

    for i := 0; i < size; i++ {
        fmt.Printf(<-ch)
    }

    elapsed := time.Since(start)
    fmt.Printf("Done! It took %v seconds!\n", elapsed.Seconds())
}

输出:

Fib(14): 610
Fib(8): 34
Fib(1): 1
Fib(5): 8
Fib(0): 1
Fib(12): 233
Fib(2): 2
Fib(13): 377
Fib(6): 13
Fib(7): 21
Fib(4): 5
Fib(3): 3
Fib(10): 89
Fib(9): 55
Fib(11): 144
Done! It took 2 seconds!

使用两个无缓冲channel的程序的第二个版本如下所示:

package main

import (
    "fmt"
    "time"
)

var quit = make(chan bool)

func fib(c chan int) {
    x, y := 1, 1

    for {
        select {
            case c <- x:
                x, y = y, x+y
            case <-quit:
                fmt.Println("Done calculating Fibonacci!")
            return
        }
    }
}

func main() {
    start := time.Now()

    command := ""
    data := make(chan int)

    go fib(data)

    for {
        num := <-data
        fmt.Println(num)
        fmt.Scanf("%s", &command)
        if num > 10000 {
            quit <- true
            break
        }
    }

    time.Sleep(1 * time.Second)

    elapsed := time.Since(start)
    fmt.Printf("Done! It took %v seconds!\n", elapsed.Seconds())
}

输出:

1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
Done calculating Fibonacci!
Done! It took 1 seconds!