反映。选择功能需要为什么?我认为这是因为频道必须是反射值?

时间:2016-06-14 21:41:48

标签: go

在什么情况下反映。选择需要什么?

我找到了一些例子,但是使用Select似乎是人为的。

任何需要反射的例子。选择是否需要正常选择?

2 个答案:

答案 0 :(得分:1)

MongoDB的人们有一个write-up recently。显然,此代码在其mongodump实用程序中正在生产中使用。

使用reflect.Select的具体代码如下所示(来自文章):

// Run multiplexer until it receives an EOF on the control channel.
func (mux *Multiplexer) Run() {
    for {
        index, value, recv := reflect.Select(mux.selectCases)
        EOF := !recv
        // note that the control channel is always at index 0
        if index == 0 {
            if EOF {
                return
            }
            muxInput, _ := value.Interface().(*muxInputSource)
            mux.selectCases = append(mux.selectCases, reflect.SelectCase{
                Dir:  reflect.SelectRecv,
                Chan: reflect.ValueOf(muxInput.collection),
                Send: reflect.Value{},
            })
        } else {
            if EOF {
                mux.writeEOF()
                mux.selectCases = append(mux.selectCases[:index], mux.selectCases[index+1:]...)
            } else {
                document, _ := value.Interface().([]byte)
                mux.writeDocument(document)[]
            }
        }
    }
}

我认为他们使用reflect.Select代替直接select的原因:

  • 在运行时确定goroutine的数量(以及通道数)(使用-j标志)。事实上,它似乎随着append动态变化。 (归功于@ cnicutar的评论)
  • 通道的类型在运行时确定。这允许他们的muxInput.collection类型成为它想要的任何东西。 (归功于@ JimB'评论)

答案 1 :(得分:0)

如果您的频道是固定的,则可以使用select观看; 但是,如果您的频道未固定并且想要观看,则可以使用reflect.Select。

有一些代码段

var (
      events  []reflect.SelectCase
      err     error
      lenHdr  = 3 // zk conn event chan, shutdown chan, children refresh chan
      lenCW   = len(z.ChildWatches)    // a channel slice:chan ChildWatche
      lenDW   = len(z.DataWatches)     //a channel slice:chan DataWatche
      lenEN   = len(z.EphemeralNodes)  //a channel slice: chan EphemeralNode
  )
  events = make([]reflect.SelectCase, lenHdr+lenCW+lenDW+lenEN)
  events[0] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(FreshChanConEvent())} // kick off the event loop
  events[1] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(z.shutdownChan)}
  events[2] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(z.refreshChildChan)}
  for i, _ := range z.ChildWatches {
      events[lenHdr+i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.Zero(reflect.TypeOf((chan zk.Event)(nil)))}
  }
  for i, _ := range z.DataWatches {
      events[lenHdr+lenCW+i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.Zero(reflect.TypeOf((chan zk.Event)(nil)))}
  }
  for i, info := range z.EphemeralNodes {
    events[lenHdr+lenCW+lenDW+i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(info.Ch)}
  }

  for {
    chosen, value, ok := reflect.Select(events)
    if chosen == xxxxx {...}

此代码正在监视频道数组(z.ChildWatches,z.DataWatches,z.EphemeralNodes)