Why there are two streams in the example given on github - chat using mdns?

In this example - https://github.com/libp2p/go-libp2p/tree/master/examples/chat-with-mdns, there are 2 goroutines spawned for each - read and write. I don’t understand the reason behind this. Why can not we just have one stream for reading and writing?

Also when the handleStream function is called. What is its role?

Code For reference

func handleStream(stream net.Stream) {

// Create a buffer stream for non blocking read and write.
rw := bufio.NewReadWriter(bufio.NewReader(stream), bufio.NewWriter(stream))

go readData(rw)
go writeData(rw)

// 'stream' will stay open until you close it (or the other side closes it).

}

if err := host.Connect(ctx, peer); err != nil {
	fmt.Println("Connection failed:", err)
}

// open a stream, this stream will be handled by handleStream other end
stream, err := host.NewStream(ctx, peer.ID, protocol.ID(cfg.ProtocolID))

if err != nil {
	fmt.Println("Stream open failed", err)
} else {
	rw := bufio.NewReadWriter(bufio.NewReader(stream), bufio.NewWriter(stream))

	go writeData(rw)
	go readData(rw)
	fmt.Println("Connected to:", peer)
}