简体   繁体   中英

Golang reflect.SelectSend does not work and get false

I'm trying to use reflect.Select to send data in a channel. The code is as following.

c := make(chan int, 1)
vc := reflect.ValueOf(c)
go func() {
    <-c
}()
vSend := reflect.ValueOf(789)
branches := []reflect.SelectCase{
    {Dir: reflect.SelectSend, Chan: vc, Send: vSend},
}
selIndex, _, sentBeforeClosed := reflect.Select(branches)
fmt.Println(selIndex)
fmt.Println(sentBeforeClosed)

But I found it doesn't work, the result is

0 
false

why do I get false ? How could I monitor a list of channels which could recv data?

If you carefully read reflect.Select documentation, you'll see that the third return value is relevant only when the direction of the case is a receive operation.

Select executes a select operation described by the list of cases. Like the Go select statement, it blocks until at least one of the cases can proceed, makes a uniform pseudo-random choice, and then executes that case. It returns the index of the chosen case and, if that case was a receive operation, the value received and a boolean indicating whether the value corresponds to a send on the channel (as opposed to a zero value received because the channel is closed). [...]

In other words, the above means that on receive operations the third return value will be true if the channel received an actual value, or false if it received the zero value for the channel item type due to the channel being closed.

But your code uses Dir: reflect.SelectSend . On send operations, it is not necessary to inspect the boolean value because the send case will either be selected or not. If it is, the first return value selIndex will be the index of the selected case, and that's all you need to know. The third return value in this case is false simply because it is the zero value of the bool type.

If you change your code to use Dir: reflect.SelectRecv , then the boolean value will have meaning, based on the above quoted documentation:

func main() {
    c := make(chan int, 1)
    vc := reflect.ValueOf(c)
    go func() {
        c <- 789
    }()
    branches := []reflect.SelectCase{
        {Dir: reflect.SelectRecv, Chan: vc},
    }
    selIndex, recVal, recOK := reflect.Select(branches)
    fmt.Println(selIndex, recVal, recOK)

    selIndex, recVal, recOK = reflect.Select(branches)
    fmt.Println(selIndex, recVal, recOK)
}

Prints:

0 789 true
0 0 false

Playground: https://go.dev/play/p/ezuc_OaK_SW

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM