为什么我的goroutine饿了?

Overview

I am writing a program where a server is launched in one goroutine. The server has a few different goroutines:

  1. The main goroutine: This handles initialization, launches a second goroutine which listens for new connections (2), and then goes into an infinite loop to act on the data received from connections (i.e., clients).
  2. The listen goroutine: This goroutine goes into an infinite loop, constantly listening for new connections. If a new connection is accepted, another goroutine is launched which listens for messages from the connection until it is closed.

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:

  1. The main goroutine: This handles intialization, registers the client with a server, launches a second goroutine to read data from the server (2), and then goes into an infinite loop to act on the data received from the server.
  2. The second goroutine: This goroutine constantly tries to read data from the server until the connection is closed.

Starvation

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.

My handler

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.