あと最近の発見と絶望は、C.selectが呼び出せないこと。select中のdefaultでnonblocking相当にできるけど、可変数なfdをselectしたい相当をどう書けばいいんだろうか。 #golang
— HiroakiKawai (@kwi) July 28, 2014reflect.Select を使います。
package main
import (
    "fmt"
    "math/rand"
    "reflect"
    "sync"
    "time"
)
func multpleSelect(chans []chan bool) (int, bool, bool) {
    // 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 bool, 100)
    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 を作るのがコストになり得るので、予め作ったまま保持しておくのが良いかと思います。

 
 

 
 
  
 
