30秒到达战场
我喜欢为此使用一个简单的计数信号量,并结合sync.WaitGroup来确保完成,正如@Parham Alvani建议的那样。(请注意,@Parham Alvani 的解决方案至少与此解决方案同样正确)(一些解释 - 我们创建一个带有缓冲区的通道 - 缓冲区大小成为 goroutine 允许并发执行的数量。每个 goroutine 在通道中放入一些内容,然后将其读回。在下面的代码中,第五个有时,该 goroutine 会被阻塞添加到通道中,直到另一个 goroutine 从通道中取出某些内容。)我还使用了“getRTT”函数来处理指向服务器的指针,因为我们在这里修改了接收器。这里的游乐场: https ://play.golang.org/p/8Rmp0kHoNFBpackage mainimport ( "fmt" "time" "sync" "math/rand")type Server struct { id uint ip string rtt time.Duration}func (s *Server) setRTT() { fmt.Printf("setting rtt for id %d\n", s.id) // do something that takes a while sleepyTime := time.Second * time.Duration(rand.Intn(5)) time.Sleep(sleepyTime) s.rtt = sleepyTime}func main() { servers := []Server{ {1,"10.10.10.0",0}, {2,"10.10.10.1",0}, {3,"10.10.10.2",0}, {4,"10.10.10.3",0}, {5,"10.10.10.4",0}, {6,"10.10.10.5",0}, {7,"10.10.10.0",0}, {8,"10.10.10.1",0}, {9,"10.10.10.2",0}, {10,"10.10.10.3",0}, {11,"10.10.10.4",0}, {12,"10.10.10.5",0}, {13,"10.10.10.0",0}, {14,"10.10.10.1",0}, {15,"10.10.10.2",0}, {16,"10.10.10.3",0}, } semaphore := make(chan struct{}, 4) // limit concurrency simply, you likely want a larger number than 4 here var wg sync.WaitGroup // necessary to ensure we complete everything - otherwise main will exit before we are done wg.Add(len(servers)) for i := range servers { go func(s *Server) { defer wg.Done() semaphore <- struct{}{} // put something in channel, will block when > 4 defer func() { <-semaphore }() // remove something from channel as this goroutine completes, allowing another goroutine to continue s.setRTT() }(&servers[i]) } wg.Wait() // wait for it! fmt.Println(servers)}示例输出:setting rtt for id 16setting rtt for id 1setting rtt for id 2setting rtt for id 3setting rtt for id 4setting rtt for id 5setting rtt for id 6setting rtt for id 7setting rtt for id 8setting rtt for id 9setting rtt for id 10setting rtt for id 11setting rtt for id 12setting rtt for id 13setting rtt for id 14setting rtt for id 15[{1 10.10.10.0 2000000000} {2 10.10.10.1 2000000000} {3 10.10.10.2 4000000000} {4 10.10.10.3 1000000000} {5 10.10.10.4 3000000000} {6 10.10.10.5 0} {7 10.10.10.0 0} {8 10.10.10.1 1000000000} {9 10.10.10.2 0} {10 10.10.10.3 4000000000} {11 10.10.10.4 1000000000} {12 10.10.10.5 2000000000} {13 10.10.10.0 4000000000} {14 10.10.10.1 3000000000} {15 10.10.10.2 4000000000} {16 10.10.10.3 1000000000}]