2014/07/29

Recent entries from same category

  1. Go に go:embed が入った。
  2. os/signal に NotifyContext が入った。
  3. 画像に再生マークつけるだけのコマンド作った。
  4. Go言語で Lisp 処理系を作った。
  5. Go 言語のスライス挿入ベンチマーク

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 by | Edit


blog comments powered by Disqus