package main import ( "fmt" "time" ) funcasyncOperation(resultChan chan<- string, id int, sem chanstruct{}) { // 获取一个信号量,表示开始一个任务 sem <- struct{}{} deferfunc() { <-sem // 任务结束时释放信号量 }() // 模拟异步操作,比如网络请求或数据处理 fmt.Println("进来执行任务了", id) time.Sleep(2 * time.Second) // 假设操作需要2秒钟 result := fmt.Sprintf("异步操作结果 %d", id) resultChan <- result // 将结果发送到channel } funcmain() { const numOperations = 20 results := make([]string, numOperations) resultChan := make(chanstring) // 创建一个用于接收结果的channel sem := make(chanstruct{}, 3) // 创建一个信号量通道,最大并发数为3 // 启动所有异步操作goroutines for i := 0; i < numOperations; i++ { go asyncOperation(resultChan, i+1, sem) } // 收集所有异步操作的结果 for i := 0; i < numOperations; i++ { // 从channel接收结果,这会阻塞直到结果可用 results[i] = <-resultChan fmt.Println("异步操作完成:", results[i]) } // 所有结果都收集完毕后,可以继续后续处理 fmt.Println("所有异步操作已完成。") }
在这个修改后的代码中,我添加了一个名为 sem 的信号量通道,其缓冲大小为3,表示最多允许3个goroutines同时运行。在 asyncOperation 函数中,每个goroutine在开始执行任务前会先向 sem 通道发送一个空结构体,以获取一个信号量。任务完成后,它会从 sem 通道中接收一个空结构体来释放信号量,从而允许其他等待的goroutines开始执行。