@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
ため、関数を実行しているゴルーチンは永久に実行されます(c <- x
この場合はブロックオン)。(発信者のスコープから外れると)共有しているチャネルから二度と読み取らないという事実はc
、それを変更しません。また、@ tux21bが指摘しているように、チャネルはまだ使用されているため、ガベージコレクションされることはありません。これは、チャネルを閉じること(チャネルの受信側に、これ以上値が来ないことを知らせることを目的としています)とは関係がなく、関数から戻らないことと関係があります。