How to find: invalid character 'F' looking for beginning of value

I really don’t know where to begin. I’ve looked on google, but nothing. I am just playing around with Channels trying to grasp the select{} feature. console returns: invalid character ‘F’ looking for beginning of value

Playground:
https://goplay.space/#7dDoM19a8Xh

here is my code in case you are on mobile:

package main

import (
	"fmt"
)

func main() {
	c, q := gen()

	receive(c, q)

	fmt.Println("about to exit")
}

func gen() (<-chan int, <-chan int) {
	c := make(chan int)
	q := make(chan int)

	go func() {
		for i := 0; i < 100; i++ {
			if i%2 == 0 {
				c <- i

			} else {
				q <- i
			}

		}
		close(q)
		close(c)
	}()

	return c, q
}
func receive(c, q <-chan int) {
	var msg1 int
	var msg2 int
	for {
		select {
		case msg1 = <-c:
			fmt.Println(msg1)
		case msg2 = <-q:
			fmt.Println(msg2)

		}
	}
}

I don’t know anything about https://goplay.space, but the same code seems to work fine (or at least run without that error) here: Go Playground - The Go Programming Language , maybe it’s a bug with the runtime there?

2 Likes

Hmmm that is very odd!

What is the reason for all the 0’s continuing to print at execution despite all the channels being closed? I thought that was the signal that there was no more values to pull.

Is there a way to have end without setting a condition in the for loop?

A closed channel still sends the zero value so that consuming the channel can be used to “test” whether it’s open or not. You can implement this test by using the following constructions: msg, ok = <-c and checking “ok”, see Go Playground - The Go Programming Language

Another option would be a “done” channel: Go Playground - The Go Programming Language

EDIT: The “done” channel solution is probably suboptimal in this case, because there are non-deterministically some number of "0"s at the end (I’ve seen 0, 1, and 2, but I think theoretically, depending on when select decides to pick the “done” channel, it could be any number?), based on whether the select grabs the “closing” channels. Best to stick with the “test” for closeness.

1 Like

Awesome thanks, I really appreciate the help! I will have to take a closer at the “comma ok idiom.”

Yup!

Also sorry this was bothering me, I realized after commenting that “returning” when a channel closed was incorrect in my implementation. Because there are two channels, the earlier solution might prematurely exit while the other channel is open (unlikely in this case but still technically wrong).

Here’s a more correct (though admittedly more complex) solution: Go Playground - The Go Programming Language, which only leaves the for loop after it confirms each channel is closed

1 Like

That is very interesting. I appreciate you sending me multiple examples. So it appears a condition is necessary in the for loop in order for the program to execute properly.

Yeah, even if you ignore the parallel/concurrent stuff and just focus on the for loop, if it has no conditions defined (i.e. it’s just for { some stuff }), unless there is a break/return in the body, it’ll loop forever.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.