Pgxpool returns "pool closed" 扫描时出错

Pgxpool returns "pool closed" error on Scan

我正在尝试在新的 go 应用程序中实现 pgxpool。尝试扫描到结构后,我不断收到“池关闭”错误。

pgx 记录器在连接后给了我这个。我以为 pgxpool 应该保持打开状态。

{"level":"info","msg":"closed connection","pid":5499,"time":"2022-02-24T16:36:33+10:30"}

这是我的路由器代码

func router() http.Handler {

    var err error

    config, err := pgxpool.ParseConfig(os.Getenv("DATABASE_URL"))

    if err != nil {
        log.Fatalln(err)
    }

    log.Println(os.Getenv("DATABASE_URL"))

    logrusLogger := &logrus.Logger{
        Out:          os.Stderr,
        Formatter:    new(logrus.JSONFormatter),
        Hooks:        make(logrus.LevelHooks),
        Level:        logrus.InfoLevel,
        ExitFunc:     os.Exit,
        ReportCaller: false,
    }

    config.ConnConfig.Logger = NewLogger(logrusLogger)

    db, err := pgxpool.ConnectConfig(context.Background(), config)

    if err != nil {
        log.Fatalln(err)
    }

    defer db.Close()

--- minio connection

rs := newAppResource(db, mc)

然后,我在帮助文件中设置了资源

type appResource struct {
   db *pgxpool.Pool
   mc *minio.Client
}

// newAppResource function to pass global var
func newAppResource(db *pgxpool.Pool, mc *minio.Client) *appResource {
    return &appResource{
        db: db,
        mc: mc,
    }
}

此代码末尾出现“pool closed”错误

func (rs *appResource) login(w http.ResponseWriter, r *http.Request) {

    var user User
    var login Login

    d := json.NewDecoder(r.Body)
    d.DisallowUnknownFields() // catch unwanted fields

    err := d.Decode(&login)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    if err != nil {
        fmt.Println("can't decode JSON", err)
    }

    if login.Email == "" {
        log.Println("empty email")
        return
    }

    log.Println(login.Email)

    log.Println(login.Password)

    if login.Password == "" {
        log.Println("empty password")
        return
    }

    // optional extra check
    if d.More() {
        http.Error(w, "extraneous data after JSON object", http.StatusBadRequest)
        return
    }

    sqlStatement := "SELECT user_id, password FROM users WHERE active = 'true' AND email = ?"

    row := rs.db.QueryRow(context.Background(), sqlStatement, login.Email)

    err = row.Scan(&user.UserId, &user.Password)

    if err == sql.ErrNoRows {
        log.Println("user not found")
        http.Error(w, err.Error(), http.StatusUnauthorized)
        return
    }

    if err != nil {
        log.Println(err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

您似乎正在执行以下操作:

func router() http.Handler {
   db, err := pgxpool.ConnectConfig(context.Background(), config)
   if err != nil {
       log.Fatalln(err)
   }
   defer db.Close()

   return appResource{db: db}
}

这个问题是 defer db.Close() 在函数 router() 结束时运行,这是在实际使用返回的 pgxPool.Pool 之前(返回的 http.Handler 将稍后在处理 http 请求时使用)。尝试使用封闭的 pgxPool.Pool 会导致您看到错误。

最简单的解决方案是简单地删除 defer db.Close(),但是您也可以考虑调用 db.Close() 作为干净关闭过程的一部分(只要您正在处理请求,它就需要保持打开状态) .

您使用的 pgxpool 与标准库不同;但是我相信 standard library docs 中给出的建议在这里适用:

It is rarely necessary to close a DB.