I have three goroutines which depend on each other, and I am coordinating them with channels. Two of the routines are writers and one is a reader to a named pipe.
However, each of these routines could have an error. For example, os.OpenFile
could fail in several of these routines. If this happens, we want to exit the routine immediately. However, if we do that, then the other routines will block because the channels will never be consumed.
How do I coordinate and handle error states across these three routines? Do I need an error channel for every single action, and then interleave checking them in every other routine?
func main() {
syscall.Mkfifo("p.pipe", 0666)
writer, _ := os.Create("output.csv")
queryDone := make(chan error)
waitingDone := make(chan error)
copyDone := make(chan error)
go func() {
// Open for reading and copy to http handler
r, _ := os.OpenFile("p.pipe", os.O_RDONLY, os.ModeNamedPipe)
n, _ := io.Copy(writer, r)
e := <-waitingDone
r.Close()
copyDone <- e
}()
go func() {
// Open for writing
pipe, _ := os.OpenFile("p.pipe", os.O_WRONLY|os.O_APPEND, os.ModeNamedPipe)
e := <-queryDone
_ = pipe.Close()
waitingDone <- e
}()
go func() {
// DB query
db, _ := sql.Open("duckdb", "")
defer db.Close()
_, err = db.Exec("COPY (select 1) TO 'p.pipe' (FORMAT CSV)")
queryDone <- err
}()
e := <-copyDone
fmt.Println("Done", e)
}