我目前正在浏览Go,并且认为goroutines的用法类似于Python生成器,尤其是Question 66。我以为66看起来很复杂,因此我将其改写为:
package main import "fmt" func fibonacci(c chan int) { x, y := 1, 1 for { c <- x x, y = y, x + y } } func main() { c := make(chan int) go fibonacci(c) for i := 0; i < 10; i++ { fmt.Println(<-c) } }
这似乎有效。几个问题:
fibonacci
main
c
go fibonacci
我喜欢@ tux21b的答案;在fib()函数中创建通道可以使调用代码清晰美观。详细说明一下,如果在调用时无法告诉函数何时停止,则只需要一个单独的“退出”通道。如果您只关心“最多X个数字”,则可以执行以下操作:
fib()
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)在大多数情况下,使用的内存似乎并不重要,但是很容易造成很大的性能差异。
make (chan int, 100)
您的fibonacci函数中有一个无限循环,因此运行它的goroutine将永远运行(c <- x在本例中为on )。您(一旦c超出了调用者的范围)就不会再从与之共享的频道中读取该事实并不会改变这一点。正如@ tux21b所指出的,该通道将永远不会被垃圾回收,因为它仍在使用中。这与关闭通道无关(其目的是让通道的接收端知道不再有值了),并且与不从函数中返回无关。
c <- x