This script doesn't work:
mkfifo pipe
echo Hello! > pipe
cat pipe # unreachable
...Because echo
waits for someone to read from pipe
before doing anything.
If there were space "inside" the pipe to store Hello!
, then echo
could exit and cat
could read from the pipe. We could accomplish this if pipe
were a normal file, but then there wouldn't be a way to limit its size.
In Go, channels act like pipes. We can add a buffer which will store some number of values at a time:
...
func main() {
// channel has a "buffer", which stores up to 1 message
channel := make(chan *byte, 1)
write("Hello!", channel)
read(channel, fmt.Println)
}
I'm not entirely sure if this satisfies your criteria, but it seems to be an effective work-around:
$ ( : < fifo & ); ( echo 'Hello!' > fifo & )
$ cat fifo
Hello!
The basic idea is to open a reader (which does not consume any data) so the the echo
can write data into the pipe. (The parentheses are just to suppress the job control output and can be omitted.)
It may be clearer to use:
$ sleep 1 < fifo & echo 'Hello!' > fifo
[1] 70954
$ sed 1q fifo
Hello!
[1]+ Done sleep 1 < fifo
$
But there's a bit of a race condition. If the sleep
terminates before echo
runs (unlikely), then the echo
will hang. It's safer to run echo
in the background.