2 回答

TA貢獻1824條經驗 獲得超8個贊
如果您只需要同時運行 n 個 goroutine,您可以擁有一個大小為 n 的緩沖通道,并在沒有剩余空間時使用它來阻止創建新的 goroutine,就像這樣
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
const ROUTINES = 2
rand.Seed(time.Now().UnixNano())
stopper := make(chan struct{}, ROUTINES)
var counter int
for {
counter++
stopper <- struct{}{}
go func(c int) {
fmt.Println("+ Starting goroutine", c)
time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
fmt.Println("- Stopping goroutine", c)
<-stopper
}(counter)
}
}
在這個例子中,你會看到你只能擁有 ROUTINES 個存活時間為 0、1 或 2 秒的 goroutine。在輸出中,您還可以看到每次一個 goroutine 結束時另一個 goroutine 是如何開始的。

TA貢獻1813條經驗 獲得超2個贊
這增加了一個外部依賴,但考慮這個實現:
package main
import (
"context"
"database/sql"
"log"
"github.com/MicahParks/ctxerrpool"
)
func main() {
// Create a pool of 2 workers for database queries. Log any errors.
databasePool := ctxerrpool.New(2, func(_ ctxerrpool.Pool, err error) {
log.Printf("Failed to execute database query.\nError: %s", err.Error())
})
// Get a list of queries to execute.
queries := []string{
"SELECT first_name, last_name FROM customers",
"SELECT price FROM inventory WHERE sku='1234'",
"other queries...",
}
// TODO Make a database connection.
var db *sql.DB
for _, query := range queries {
// Intentionally shadow the looped variable for scope.
query := query
// Perform the query on a worker. If no worker is ready, it will block until one is.
databasePool.AddWorkItem(context.TODO(), func(workCtx context.Context) (err error) {
_, err = db.ExecContext(workCtx, query)
return err
})
}
// Wait for all workers to finish.
databasePool.Wait()
}
- 2 回答
- 0 關注
- 209 瀏覽
添加回答
舉報