1

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

pgx 记录器在连接后给了我这个。我认为 pgxpool 应该保持开放。

{"level":"info","msg":"关闭连接","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,
    }
}

此代码末尾出现“池已关闭”错误

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
    }
4

1 回答 1

1

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

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的确实与标准库不同;但是我相信标准库文档中给出的建议在这里适用:

很少需要关闭数据库。

于 2022-02-24T18:19:30.867 回答