2017-12-13 46 views
1

私は、発電機として利用される2つの読み取り専用チャネル<-chan Eventを持っています。チャネルから値を検査する

type Event struct{ 
    time int 
} 

ように私はそれらの値を読むことができます:私はあまりtimeフィールドでEventを選択する必要がありますので、私はイベント駆動型シミュレーションのために、これらのチャネルを使用

for { 
    select { 
    case <-chan1: 
     // do something 
    case <-chan2: 
     //do something 
    } 

各チャネルからどの値が入力されているかを調べて、どれを読み込むかを選択することはできますか?操作<-chan1はチャネルから値を取り、それを元に戻すことはできません(読み取り専用チャネル)。

+0

なぜローカルバッファを作成し、その中にすべてのイベントを格納し、そのバッファから選択しますか? –

+0

@ParhamAlvaniはローカルバッファなしでそれをやりたいエレガントなソリューションを探してください –

+0

別の提案として、MutexとCondVarを使って構造体のようなチャネルを実装することができます。このタイプのソリューションが必要な場合は、実装をアップロードできます。 –

答えて

3

あなたのバージョンのgoチャネル構造を実装できます。たとえば、サイズ制限なしのgoチャネルのような実装の後で、最初の要素を調べることができます。

package buffchan 

import (
    "container/list" 
    "sync" 
) 

// BufferedChannel provides go channel like interface with unlimited storage 
type BufferedChannel struct { 
    m *sync.Mutex 
    l *list.List 
    c *sync.Cond 
} 

// New Creates new buffer channel 
func New() *BufferedChannel { 
    m := new(sync.Mutex) 
    return &BufferedChannel{ 
     m: m, 
     l: list.New(), 
     c: sync.NewCond(m), 
    } 
} 

// Append adds given data at end of channel 
func (b *BufferedChannel) Append(v interface{}) { 
    b.m.Lock() 
    defer b.m.Unlock() 

    b.l.PushBack(v) 
    b.c.Signal() 

} 

// Remove removes first element of list synchronously 
func (b *BufferedChannel) Remove() interface{} { 
    b.m.Lock() 
    defer b.m.Unlock() 

    for b.l.Len() == 0 { 
     b.c.Wait() 
    } 

    v := b.l.Front() 
    b.l.Remove(v) 

    return v.Value 
} 

// Inspect first element of list if exists 
func (b *BufferedChannel) Inspect() interface{} { 
    b.m.Lock() 
    defer b.m.Unlock() 

    for b.l.Len() == 0 { 
     return nil 
    } 

    return b.l.Front().Value 
} 

// AsyncRemove removes first element of list asynchronously 
func (b *BufferedChannel) AsyncNonBlocking() interface{} { 
    b.m.Lock() 
    defer b.m.Unlock() 

    for b.l.Len() == 0 { 
     return nil 
    } 

    v := b.l.Front() 
    b.l.Remove(v) 

    return v.Value 
} 
+0

'AsyncRemove'は' AsyncNonBlocking'という名前の方がいいかもしれません。 – zerkms