coproc utility is not the same as utility & in bash.
With coproc utility you get an array, COPROC, that contains the standard input and output filedescriptors of utility. You may then do things like
#!/bin/bash
coproc bc -l
for (( k = 0; k < 50; ++k )); do
printf '2.3*%d + 1\n' "$k" >&${COPROC[1]}
read -u "${COPROC[0]}" a
printf '%.2f\n' "$a"
done
kill "$COPROC_PID"
Here, bc -l is a co-process and acts like a "arithmetic computation service" for the shell loop, taking expressions to compute on its standard input and giving back results on its standard output.
As far as I can tell, bash also only supports one co-process at any one time.
The ksh93 shell also supports co-processes, but the syntax is totally different (but somewhat sleeker). This is the equivalent ksh93 script:
#!/usr/bin/ksh93
bc -l |&
coproc_pid=$!
for (( k = 0; k < 50; ++k )); do
print -p -f '2.3*%d + 1\n' "$k"
read -p a
printf '%.2f\n' "$a"
done
kill "$coproc_pid"
Here, it's the -p option to print and read that makes it communicate with the co-process (the process started with |&) rather than using some explicit filedescriptor.