#2622·pgx

panic: 关闭已关闭的通道 — `cleanupDone` 附近的 `status` 保护是一个未同步的测试和设置 (包括重现器)

作者: martinrode创建于 2026年8月10日更新于 2026年8月15日

// go run . -> panics // go run . -fix -> does not package main import ( "context" "database/sql" "flag" "fmt" "math/rand/v2" "os" "sync" "time"

"GitHub.com/jackc/pgx/v5"
"GitHub.com/jackc/pgx/v5/stdlib"

) var ( fix = flag.Bool("fix", false, "begin the transaction on an uncancellable context") workers = flag.Int("workers", 32, "concurrent workers") seconds = flag.Int("seconds", 25, "run time") dsn = flag.String("dsn", "host=localhost port=5432 dbname=postgres sslmode=disable", "") ) func main() { flag.Parse() db, err := sql.Open("pgx", *dsn) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(2) } defer db.Close() db.SetMaxOpenConns(*workers) db.SetMaxIdleConns(*workers) if err := db.PingContext(context.Background()); err != nil { fmt.Fprintln(os.Stderr, "no postgres:", err) os.Exit(2) } deadline := time.Now().Add(time.Duration(*seconds) * time.Second) var wg sync.WaitGroup for range *workers { wg.Add(1) go func() { defer wg.Done() for time.Now().Before(deadline) { round(db) } }() } wg.Wait() fmt.Println("survived") } func round(db *sql.DB) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() conn, err := db.Conn(ctx) if err != nil { return } defer conn.Close() var pgxConn *pgx.Conn if err := conn.Raw(func(dc any) error { pgxConn = dc.(*stdlib.Conn).Conn() return …