Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The code of chan part in the Reflection chapter is a little bit unintuitive #736

Closed
UponTheSky opened this issue Feb 11, 2024 · 1 comment

Comments

@UponTheSky
Copy link
Contributor

UponTheSky commented Feb 11, 2024

Hi, it is a great pleasure to go through this wonderful content. I am learning a lot from this.

While I was reading and testing the chan part in the chapter Reflection, the loop part was not much intuitive to me.

for v, ok := val.Recv(); ok; v, ok = val.Recv() {
  // ...
}

So I tried this code instead(at first, I thought it might be a typo):

for v, ok := val.Recv(); ok; {
  // ...
}

However, the test didn't seem to be running. So mimicking the code in the page(the docs doesn't say much about Value.Recv), and I've got this result:

package main

import (
	"fmt"
	"reflect"
)

func main() {
	channel := make(chan int)

	go func() {
		channel <- 42
		channel <- 7
		close(channel)
	}()

	val := reflect.ValueOf(channel)
	count := 0

	for v, ok := val.Recv(); ok; {
		fmt.Print(v)
		count++

		if count > 100 {
			fmt.Println("\nInfinite loop")
			break
		}
	}
}
  • the result
4242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242
Infinite loop

Program exited.

From my understanding, it seems that Value.Recv() doesn't behave the same as the <- operator when it is in the condition statement of a for loop - not popping the front element from the queue.

However, since the original code passes the test, I tweaked the code a little and printed the values:

package main

import (
	"fmt"
	"reflect"
)

func main() {
	channel := make(chan int)

	go func() {
		channel <- 42
		channel <- 7
		close(channel)
	}()

	val := reflect.ValueOf(channel)

	for v, ok := val.Recv(); ok; {
		fmt.Println("first", v)
		v, ok = val.Recv()
		fmt.Println("second", v)
	}
}
  • the result is:
first 42
second 7
first 7
second 0

So in the conclusion, the behavior of value.Recv is hardly expectable(Moreover, if I ignore the ok variable in the body as v, _ = val.Recv(), I get the infinite loop again). Perhaps this is why the original author wrote the code like this.

Nevertheless, personally I think this line easily confuses newbies like me. It is neither using the familiar <- operator nor val := range channel. Furthermore, it gives the impression that we should poll the channel twice to get the value we want.

If it is okay, I would like to make a simple fix on this part as a PR.

@UponTheSky UponTheSky changed the title The chan part in the Reflection chapter is not working as expected. The code of chan part in the Reflection chapter is a little bit unintuitive Feb 11, 2024
@UponTheSky
Copy link
Contributor Author

I close this issue due to merged PR #737

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant