Go の例(2) (ゴルーチン)
次にゴルーチンを使ったものを考えます。GenerateDecimal をゴルーチンを使って以下のように書き直します。これはクロージャーを使っているのでクロージャーの代わりにゴルーチンを使っているわけではありません。
func (xyz *NumbersGenerator) GenerateDecimal() *IteratorSimpleImpl_int { current_digit := 0 ch := make(chan int) coBody := func(ch chan int) { number := newLongDecimal([]int{}) square_difference := newLongDecimal([]int{3}) nums := newNumbers(number, square_difference, 0) for { ch <- nums.GetNextDecimalDigit() } } go coBody(ch) next := func() bool { val, ok := <-ch current_digit = val return ok } getCurrent := func() int { return current_digit } setCurrent := func(val int) { } return newIteratorSimpleImpl_int(next, getCurrent, setCurrent) }
次にクロージャーを使わないように書き直します。チャネルを使ってイテレーターを実現する IteratorChannelImpl_int を作ります。
type IteratorChannelImpl_int struct { ch chan int current_digit int } func newIteratorChannelImpl_int(ch chan int) *IteratorChannelImpl_int { xyz := new(IteratorChannelImpl_int) xyz.ch = ch xyz.current_digit = 0 return xyz } func (xyz *IteratorChannelImpl_int) GetCurrent() int { return xyz.current_digit } func (xyz *IteratorChannelImpl_int) SetCurrent(value int) { xyz.ch <- value } func (xyz *IteratorChannelImpl_int) MoveNext() bool { val, ok := <-xyz.ch xyz.current_digit = val return ok } func (xyz *IteratorChannelImpl_int) Take(count int) []int { res := make([]int, count) iter := xyz for i := 0; i < count && iter.MoveNext(); i++ { res[i] = iter.GetCurrent() } return res }
NumbersGenerator を IteratorChannelImpl_int を使うように書き直します。これでクロージャーを使わない(一部)バージョンができました。
type NumbersGenerator struct { generator *IteratorChannelImpl_int } func newNumbersGenerator() *NumbersGenerator { xyz := new(NumbersGenerator) xyz.generator = xyz.GenerateDecimal() return xyz } func (xyz *NumbersGenerator) GetNextDecimalDigit() int { xyz.generator.MoveNext() return xyz.generator.GetCurrent() } func (xyz *NumbersGenerator) GenerateDecimal() *IteratorChannelImpl_int { ch := make(chan int) coBody := func(ch chan int) { number := newLongDecimal([]int{}) square_difference := newLongDecimal([]int{3}) nums := newNumbers(number, square_difference, 0) for { ch <- nums.GetNextDecimalDigit() } } go coBody(ch) return newIteratorChannelImpl_int(ch) }
まだクロージャーを使っているところがあるので今後検討していきます。