There's no right or wrong in this case. Specific cases work best in
one way or the other, and people tend to look at the context to create
a simple solution that solves specific problem at hand.
That said, I wrote this while facing a problem related to the one you
seem to describe:
http://blog.labix.org/2011/10/09/death-of-goroutines-under-control
--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/plus
http://niemeyer.net/twitter
http://niemeyer.net/blog
-- I'm not absolutely sure of anything.
First off, whoa, formatting fail. Gmail hates the 80 char wide text, eh? I've modified this email to include a better formatted message in the reply text at the bottom.Thanks Kyle, that sounds like the best solution that I've heard of so far. So, you're suggesting something likefunc (this *Client) Send(data []byte) os.Error {
request := new(Request)request.data = datarequest.response_channel = make(chan os.Error)
select {case v, ok <- this.closing_channel:
if !ok { return os.NewError("unable to send") }return os.NewError("unexpected closing value")case this.send_channel <- request:return <-request.response_channel}return os.NewError("unreachable")}and this works okay (read: doesn't panic) in all four cases where the sending_channel and the closing_channel are each either open or closed?
you can arrange that whenever something tries to send some
data down a channel to the writer, it also reads on a channel
that is closed when the writer quits.
then there's no chance of a panic.
this kind of thing (written in haste!):
type writer struct {
f io.Writer
data chan<- []byte
done chan bool
}
func (w *writer) writerProc() {
for{
data := <-w.data
n, err := w.f.Write(data)
if err != nil {
close(f.done)
break
}
}
}
func (w *writer) Write(buf []byte) {
select {
case w.data <- buf:
case <-done: