Getting unordered output for unbuffered channels

Yes, and that’s why there is no guarantee about the ordering.
Based on the code you provided above, I’m guessing the producer code is something like this:

go func() {
   ....
   p.logCh <- process
   // it's actually possible that another goroutine send another 
   // process to p.logCh in different goroutine after the line above
   // and before the log.Printf line below
   log.Printf("<the_timestamp> <the_process_id> sent")
   ....
}

So, it’s possible that the flow of your program is something like this:

  1. in 1st nanosecond you created 2 goroutine, goroutine A and goroutine B
  2. in 2nd nanosecond, goroutine A send an item X to the channel
  3. in 3rd nanosecond, goroutine B send an item Y to the channel
  4. in 4th nanosecond, goroutine B log “4 Y ended and sent to channel”
  5. in 5th nanosecond, goroutine A log “5 X ended and sent to channel”

as a result, you will see that Y logged before X, but actually X is sent first before Y.

What’s the solution? Well, you should think that sending an item to a channel and logging the event as a single operation that should be atomic (can’t be overlapped with other operation). One way to do this is using mutex. Before sending an item to a channel, lock the mutex first, then log the event, then unlock the mutex.