I am writing a program where a server is launched in one goroutine. The server has a few different goroutines:
The server seems to work well. I can successfully add many new connections, and I can also send data on these new connections after they are initially accepted by the server.
My client is fairly simple. There are two goroutines as well:
I'm having a huge issue with goroutine starvation on the client. Specifically, the second goroutine of the client always starves. Here's the source of the goroutine that's starving:
func receiver() {
for {
msg, err := bufio.NewReader(conn).ReadString(byte(protocol.EndOfMessage))
if err != nil {
fmt.Printf("Disconnected from server %v.
", conn.RemoteAddr())
return
}
if len(msg) < 2 {
continue
}
receiverToHandler <- msg[1 : len(msg)-1]
}
}
I am certain that a message is being sent from the server to the client. I am also sure that the message being sent ends in protocol.EndOfMessage
. I am also certain that my method of getting data from the server is correct since I use the same code to register the client, only instead of running it in an infinite loop I allow it a prespecified number of attempts.
For some reason, my client will not receive data.
To be certain that I am not misunderstanding the nature of goroutines, if I replace the above code with this:
func receiver() {
for {
fmt.Println("In the receiver goroutine!")
}
}
The goroutine works exactly as expected: everything functions exactly as before, but "In the receiver goroutine!" is constantly printed. So the routine is certainly executing correctly in this case.
func handleMessage(debug bool) {
select {
case msg := <-receiverToHandler:
update(msg, debug)
default:
/* if debug {
* fmt.Printf("Nothing received!
")
* }
*/
}
}
Right now, update(msg, debug)
just calls fmt.Println(msg)
.
Is there anything I can do to cleanly solve this problem? I feel like giving away priority / forcing the scheduler to run is a hacky solution to this problem.