2014-01-09 67 views
5
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當試圖向封閉通道插入值時,避免恐慌

我沒有尋找替代方法(如閉包)來實現同樣的事情,只是試圖更好地理解渠道。

回答

7

Close是goroutine發送到一個頻道的好方法,用信號通知接收方您已完成此頻道。相反(你的問題)恕我直言撤回,至少直接。你可以添加一個其他的信道完成哪個信號端到你的斐波那契生成goroutine。

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)) 
}