为了账号安全,请及时绑定邮箱和手机立即绑定

reflect.Select 函数是需要为什么?我认为这是因为通道必须是反射值?

reflect.Select 函数是需要为什么?我认为这是因为通道必须是反射值?

Go
UYOU 2022-01-17 18:17:32
在什么情况下会需要reflect.Select?我找到了例子,但 Select 的使用似乎是做作的。任何示例,其中 reflect.Select 比正常选择是必要的?
查看完整描述

2 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

最近有一篇来自 MongoDB 的人的文章。显然,此代码在其实用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 的评论)


查看完整回答
反对 回复 2022-01-17
?
桃花长相依

TA贡献1860条经验 获得超8个赞

如果您的频道是固定的,您可以使用选择观看它们;但是,如果您的频道不固定并且您想观看它们,则可以使用 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)


查看完整回答
反对 回复 2022-01-17
  • 2 回答
  • 0 关注
  • 243 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信