我喜欢@tux21b的答案;在fib()
函数中创建通道可以使调用代码简洁美观.更详细地说,如果无法在调用函数时告知函数何时停止,则只需要一个单独的"退出"通道.如果你只关心"数字到X",你可以这样做:
package main
import "fmt"
func fib(n int) chan int {
c := make(chan int)
go func() {
x, y := 0, 1
for x < n {
c <- x
x, y = y, x+y
}
close(c)
}()
return c
}
func main() {
// Print the Fibonacci numbers less than 500
for i := range fib(500) {
fmt.Println(i)
}
}
如果您想要这样做,这有点草率,但我个人更喜欢这样做,而不是测试调用者的条件,然后通过单独的渠道发出退出的信号:
func fib(wanted func (int, int) bool) chan int {
c := make(chan int)
go func() {
x, y := 0, 1
for i := 0; wanted(i, x); i++{
c <- x
x, y = y, x+y
}
close(c)
}()
return c
}
func main() {
// Print the first 10 Fibonacci numbers
for n := range fib(func(i, x int) bool { return i < 10 }) {
fmt.Println(n)
}
// Print the Fibonacci numbers less than 500
for n := range fib(func(i, x int) bool { return x < 500 }) {
fmt.Println(n)
}
}
我认为这只是取决于特定情况的具体情况,你是否:
- 当您通过以下方式创建生成器时,通知生成器何时停止
- 传递要生成的显式数量的值
- 传递目标值
- 传递确定是否继续进行的函数
- 给生成器一个"退出"通道,自己测试值,并告诉它在适当的时候退出.
要总结并实际回答您的问题,请执行以下操作:
由于较少的上下文切换,增加通道大小将有助于提高性能.在这个简单的例子中,性能和内存消耗都不是问题,但在其他情况下,缓冲通道通常是一个非常好的主意.make (chan int, 100)
使用的内存在大多数情况下似乎并不重要,但它很容易对性能产生重大影响.
您在函数fibonacci
中有一个无限循环,所以运行它的goroutine将永远运行(在本例中是c <- x
上的挡路).事实上(一旦c
超出了调用方的范围),您就再也不会从与其共享的通道中读取数据了,这并不能改变这一点.正如@tux21b指出的那样,该通道永远不会被垃圾收集,因为它仍在使用中.这与关闭通道(其目的是让通道的接收端知道不会再有值)无关,也与不从函数返回有关.