> I often want to wait for data from multiple io.Readers or a mix of
> io.Readers and channels. The go way to do this seems to do a select
> on a set of channels which means I need to convert an io.Reader to a
> channel. Are there any helper functions to do this?
If it's just multiple io.Readers, try io.MultiReader.
Dave.
The io.Reader interface is geared towards streams of bytes, and it
will be difficult to interleave them with useful results. What kinds
of data are you trying to process?
package main
import ( "io" "log" "net" "os" "os/signal" "syscall")
type myconn struct { net.Conn enforced bool}
func awaitSignal(sigchan <-chan os.Signal, connections map[*myconn]*myconn) { for { <-sigchan log.Println("received signal, closing all connections...") // you would not do this inside the signal handler usually for conn := range connections { conn.enforced = true conn.Close() delete(connections, conn) } }}
func echo(conn *myconn) { // Echo all incoming data.
io.Copy(conn, conn) // Shut down the connection. log.Println("lost connection") if !conn.enforced { log.Println("doing cleanup work") }
conn.Close() return
}
func main() { c := make(chan os.Signal, 2) signal.Notify(c, os.Interrupt, syscall.SIGHUP) connections := make(map[*myconn]*myconn) go awaitSignal(c, connections) l, err := net.Listen("tcp", ":2000") if err != nil { log.Fatal(err) } defer l.Close() for { // Wait for a connection. conn, err := l.Accept() if err != nil { log.Fatal(err) } log.Println("new connection") newconn := &myconn{conn, false} connections[newconn] = newconn go echo(newconn) }}