2014/07/29

reflect.Select を使います。

package main

import (
    "fmt"
    "math/rand"
    "reflect"
    "sync"
    "time"
)

func multpleSelect(chans []chan bool) (intboolbool) {
    // chans の数分 select-case 文を作る
    cases := make([]reflect.SelectCase, len(chans))
    for i, ch := range chans {
        cases[i] = reflect.SelectCase{
            Dir: reflect.SelectRecv,
            Chan: reflect.ValueOf(ch),
        }
    }

    // 一括で select
    i, v, ok := reflect.Select(cases)
    return i, v.Interface().(bool), ok
}

func main() {
    rand.Seed(time.Now().UnixNano())

    // 100個の chan を作るよ
    chans := make([]chan bool100)
    for i := 0; i < 100; i++ {
        chans[i] = make(chan bool)
    }


    // 非同期で100個の chan を同時に待つ
    var wg sync.WaitGroup
    go func() {
        wg.Add(1)

        if ch, v, ok := multpleSelect(chans); ok {
            fmt.Printf("I am chan-%v, value is %v\n", ch, v)
        }
        wg.Done()
    }()

    // ランダムな chan に true を送る
    chans[rand.Int() % len(chans)] <- true

    wg.Wait()
}

何度も繰り返して待つ場合は、その都度 SelectCase を作るのがコストになり得るので、予め作ったまま保持しておくのが良いかと思います。

Posted at 14:30 | WriteBacks () | Edit
Edit this entry...

wikieditish message: Ready to edit this entry.






















A quick preview will be rendered here when you click "Preview" button.