我喜欢@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 指出的那样,通道永远不会被垃圾收集,因为它仍在使用中。这与关闭通道无关(其目的是让通道的接收端知道不会有更多值出现)以及与不从您的函数返回有关的一切。