尝试将值插入封闭通道时避免恐慌

时间:2014-01-09 06:23:31

标签: go

package main

import (
    "fmt"
    "time"
)

func fib() chan int {
    c := make(chan int)

    go func() {
        c <- 0
        c <- 1

        n, m := 0, 1
        for {
            temp := n + m
            n = m
            m = temp
            c <- m // This results in panic, when the channel is closed
        }
    }()

    return c
}

func main() {
    start := time.Now()
    var lastFib int
    c := fib()

    for i := 0; i != 1000000; i++ {
        lastFib = <-c
    }

    close(c)
    fmt.Println(lastFib)
    fmt.Println(time.Now().Sub(start))
}

以最惯用的方式,当通道关闭时,如何避免goroutine中的恐慌?或者我应该避免使用close吗?

我不是在寻找替代方法(例如闭包)来实现同样的目的,只是想更好地理解频道。

2 个答案:

答案 0 :(得分:7)

Close是goroutine发送到频道的好方法,用于通知接收方您已完成此频道。反过来(你的问题)是IMHO可撤销,至少是直接的。你可以添加一个其他通道来完成你的fibonacci生成goroutine的任务结束。

答案 1 :(得分:1)

以下是您的示例的修改版本,该版本以允许(但不一定是明智的)方式使用频道:

package main

import (
    "fmt"
    "time"
)

func fib(c chan int) {
    c <- 0
    c <- 1

    n, m := 0, 1
    for {
        temp := n + m
        n = m
        m = temp
        c <- m
        if m > 100000000 {
            close(c)
            break
        }
    }
}

func main() {
    start := time.Now()
    lastFib, newFib := 0, 0
    ok := true
    c := make(chan int)
    go fib(c)

    for {
        newFib, ok = <-c
        if !ok {
            fmt.Println(lastFib)
            break
        }
        lastFib = newFib
    }

    fmt.Println(time.Now().Sub(start))
}