Ответ
Runnable - горутина готова к выполнению, но ожидает свободного процессора. Она находится в очереди планировщика.
Waiting - горутина заблокирована (например, на канале, мьютексе, sleep и т.д.) и не может выполняться, пока не произойдет событие, которое ее разблокирует.
Пример:
go func() {
time.Sleep(time.Second) // Waiting
ch <- 1 // Runnable после отправки
}()
val := <-ch // Waiting, пока не придут данные
Разница: Runnable активна и ждет ресурсов CPU, а Waiting пассивно ожидает внешнего события.