チャネルとrange

チャネルから送られてくるデータは、for ループの range で受けることもできる。

for v := チャネル { 処理 }

チャネルの場合、スライスやマップと違って返り値は多値ではない。あと、チャネルにデータを送る側では、送信が終わったらチャネルを close する必要がある。
次の例は、二分木にチャネルを使ってデータを送信する each 関数を追加したものだ。

package main

import (
    "fmt"
)

type Item interface {
    Eq(Item) bool
    Less(Item) bool
}

type Node struct {
    item Item
    left, right *Node
}

func newNode(x Item) *Node {
    p := new(Node)
    p.item = x
    return p
}

func insertNode(node *Node, x Item) *Node {
    switch {
        case node == nil: return newNode(x)
        case x.Eq(node.item): return node
        case x.Less(node.item):
            node.left = insertNode(node.left, x)
        default:
            node.right = insertNode(node.right, x)
    }
    return node
}

func foreachNode(f func(Item), node *Node) {
    if node != nil {
        foreachNode(f, node.left)
        f(node.item)
        foreachNode(f, node.right)
    }
}

type Tree struct {
    root *Node
}

func newTree() *Tree {
    return new(Tree)
}

func (t *Tree) insertTree(x Item) {
    t.root = insertNode(t.root, x)
}

func (t *Tree) foreachTree(f func(Item)) {
    foreachNode(f, t.root)
}

func (t *Tree) each() chan Item {
    ch := make(chan Item)
    go func() {
        t.foreachTree(func(x Item) { ch <- x })
        close(ch)
    }()
    return ch
}

type Int int

func (n Int) Eq(m Item) bool {
    return n == m.(Int)
}

func (n Int) Less(m Item) bool {
    return n < m.(Int)
}

func main() {
    a := newTree() b := []int { 5,6,4,3,7,8,2,1,9,0 }
    for _, x := range b {
        a.insertTree(Int(x))
    }
    for x := range a.each() {
        fmt.Println(x)
    }
}

for ループの range には二分木の each 関数を呼び出していて、その each 関数では、データを一つずつチャネルに送信し、最後にチャネルを close している。
実行結果はこう:

^o^ > go run go_range.go
0
1
2
3
4
5
6
7
8
9

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください