以前にGO言語での並列計算の仕組みについてについて質問をさせていただきました。
今回はそれをもう少し発展させたいのですが、スタックしてしまい、また皆様のお知恵を拝借したく、ここで質問させていただいています。

まずtoy scriptを示した後に、質問させていただきます。

package main

import (
      "fmt"
      "math/rand"
      "time"
      "sync"
      "runtime"
)

var wg sync.WaitGroup

func Sleep() {
    defer wg.Done()

    r := rand.Intn(3);
    if r == 0 {
      time.Sleep(10 * time.Millisecond) //0.01秒停止
    } else if r == 1 {
      time.Sleep(100 * time.Millisecond)  //0.1秒停止
    } else if r == 2 {
      time.Sleep(3000 * time.Millisecond) //3秒停止
    }
}

func main() {
  N := 8;
  runtime.GOMAXPROCS(N)

  idx := 0;
  for i:=0; i<18; i++ {
    fmt.Println("process:", i)
    wg.Add(1)
    idx += 1;
    go Sleep();
    if idx%N == 0 {
        wg.Wait();
    }
  }

  wg.Wait();
}

このscriptでは、goroutineを用いまして、Sleep functionを動かしています。

このfunctionでは、ランダムの数字により、Sleepの時間を変えるようにしています。
8個並列して計算させますと、そのうちの一個以上で「3秒停止」になるように設定しています。
この場合、「wg.Wait()」があるため、他の計算が終了していても、8つ中一つでも「3秒停止」があれば、その回では「3秒間停止」する必要が出てきてしまいます。

質問ですが、goroutineでは、終わったものから次の計算をさせるような機能はあるのでしょうか?

具体的には、以下のようなことを想定しております。
8つ中1つだけ「3秒停止」であり、他7つは「0.1秒停止」の場合、
0.1秒停止が終わった7つのプロセスだけ進むようなことは可能でしょうか?
ただし、最大8プロセスだけ動かすことを仮定しております。
(実際には、それ以上動かしますと、プロセス間で干渉が起こり、計算時間が長くなってしまいますので。)

ご教授、よろしくお願いします。