←back to thread

Go channels are bad

(www.jtolds.com)
298 points jtolds | 1 comments | | HN request time: 0.282s | source
Show context
Animats ◴[] No.11211091[source]
Good points.

The author points out that channel teardown is hard. He's right. Figuring out how to shut down your Go program cleanly can be difficult, especially since calling "close" on a closed channel causes a panic. You have to send an EOF on each channel so the receiver knows to stop. When you have a pair of channels going in opposite directions between two goroutines, and either end can potentially initiate shutdown, it gets messy.

At least in the original implementation, "select" for more than one option was really slow and complex. The single-input case was handled efficiently with generated code, but for N > 1, a very general library mechanism with several heap allocations for each message was used. This means having both a wait for data and a timeout in a select puts you through the slow path. Not good. Someone did an analysis of existing programs and found that N=1 was most common, N=2 was reasonably common, and N>2 was rare. N=2 needs special case support.

QNX interprocess messaging has a similar architecture. But they don't have the panic on close problem, and timeout is handled efficiently. So you can generally shut things down by closing something. As each process is notified about the close, it closes any channels with which it is involved, even if some other process has already closed them. The closes thus cascade and everything shuts down cleanly. Processes that time out at a message receive check to see if the rest of the system is still running, and shut down if it's not.

Go's "share by communicating" would be more useful if Go had Rust's borrow checker, so you could share data without races. Yes, Go has a run-time race detector, but that's only useful if races are common enough that they occur during testing.

replies(3): >>11211222 #>>11211330 #>>11211375 #
1. helper ◴[] No.11211222[source]
The panic when calling close on a closed channel is a bit annoying. Recently I've been using x/net/context to signal goroutines instead of closing a channel. The CancelContext allows you to call cancel multiple times.