You can check if a channel is closed or not. You can even use it gracefully as an iterator.
To be exact: you cannot "non-destructively" check if a channel is closed. I.e.: the way to check is by using a select statement to do a "soft write", I.e. "try to send this value but don't panic if it fails." Same for reading. This means you can't check the state of a channel without modifying it if it isn't closed.
Graceful shutdown of systems with lots of asynchronous communication is hard, but this makes it harder than it has to be.
*sigh, after all that time I still make this mistake. Goes to show how often I actually use channels. :/