Probably because neither goroutine have been scheduled so far to be able to send something, try adding some minimal sleep to force a reschedule to another go routine
This is what happens in both situations, until the select is hit:
Prepare channels
start 1. goroutine
start 2. goroutine
Now with default clause:
Neither ch1 nor ch2 currently hold data, as no other gorotine had time do send something
default is “selected”.
Without default:
Neither ch1 nor ch2 currently hold data, as no other gorotine had time do send something
But there is no default, this go routine has no way to continue without having received data from any channel, so it puts itself to sleep and hands over the control to the scheduler
the scheduler randomly hands over control to one of the go routines marked as “ready to continue”.
This will send instantly send data over “its” channel back to the main go routine.
Hands back to scheduler
scheduler knows that the main routine could continue, though it still selects randomly between the main routine and the other pending sender. (therefore the other sender might or might not put something in the channel)
Main got control directly or later, and now picks randomly from one of the available channels.