数据库连接在第一个请求后关闭

数据库连接在第一个请求后关闭

问题内容

我在golang上写api,遇到了错误。在一个请求服务器返回错误后,sql 数据库已关闭。我想通过上下文传输数据库连接。

main.go

func main() {    app := fiber.new()    db, err := sqlx.connect("pgx", os.getenv("postgresql_url"))    if err != nil {        panic(err)    }    if err = db.ping(); err != nil {        panic(err)    }    db.setmaxopenconns(10)    db.setmaxidleconns(5)    db.setconnmaxlifetime(5 * time.minute)    db.setconnmaxidletime(5 * time.minute)    defer db.close()    configure_router.configurerouter(app, db)    if err = app.listen(os.getenv("port")); err != nil {        log.fatalln(err)    }}

登录后复制

configure_router.go

func configurerouter(app *fiber.app, db *sqlx.db) {    //middlewares    app.use(logger.new(logger.config{        format: "[${ip}]:${port} ${time} ${status} - ${method} ${path}",    }))    app.use(cors.new(cors.config{        //alloworigins: "http://localhost:3000",        allowheaders: "origin, content-type, accept",    }))    app.use("/api", func(ctx *fiber.ctx) error {        ctx.context().setuservalue("dbconn", db)        return ctx.next()    })    //authentication endpoints    app.post("api/register", register.register)    app.post("api/auth/login", login.login)}

登录后复制

注册.go

func register(ctx *fiber.ctx) error {    conn := ctx.context().uservalue("dbconn").(*sqlx.db)    var in in    if err := ctx.bodyparser(&in); err != nil {        return make_response.makeinforesponse(ctx, fiber.statusunprocessableentity, 1, err.error())    }    if in.email == "" || in.password == "" {        return make_response.makeinforesponse(ctx, fiber.statusbadrequest, 1, "incorrect data input")    }    elementexist := false    err := conn.get(&elementexist, "select exists(select email from users where email = $1)", in.email)    // here programm fall in second request    if err != nil {        return make_response.makeinforesponse(ctx,fiber.statusinternalservererror, 1, err.error())    }    if elementexist {        return make_response.makeinforesponse(ctx, fiber.statusbadrequest, 1, "user already registered!")    }    passwordhash, err := hash_passwords.hashpassword(in.password)    if err != nil {        return err    }    _, err = conn.exec("insert into users (email, password_hash) values ($1, $2)", in.email, passwordhash)    if err != nil {        return make_response.makeinforesponse(ctx, fiber.statusinternalservererror, 1, err.error())    }    return make_response.makeinforesponse(ctx, fiber.statusok, 0, "registration was successful!")}

登录后复制

如果我在 /api/register 中发送请求并且用户已经在第一个请求中注册,我会得到

要求:

{  "email": "[email protected]",  "password": "123123123"}

登录后复制

第一反应:

{   "error_code": 0,   "message": "user already registered!"}

登录后复制

但是如果我想发送另一个请求,我会得到:

{   "error_code": 1,   "message": "sql: database is closed",}

登录后复制

正确答案

我想通过上下文传输数据库连接。

不要。这不仅是不好的做法,而且实际上是 fasthttp.requestctx 本身在每次请求后关闭数据库。上下文应仅包含请求特定值。全局数据库连接几乎不是特定于请求的。

请参阅 setuservalue 的文档,特别是最后一个段落:

从顶层requesthandler返回后,所有值都会从ctx中删除。此外,在从 ctx 中删除值之前,会在每个实现 io.closer 的值上调用 close 方法。

一个快速修复方法是在闭包中捕获数据库:

func Register(db *sqlx.DB) (fn func(*fiber.Ctx) error) {    return func(ctx *fiber.Ctx) error {        // ...        elementExist := false        err := db.Get(&elementExist, "select exists(select email from users where email = $1)", in.Email)        // ...    }}// ...// delete this or comment it out// app.Use("/api", func(ctx *fiber.Ctx) error {//    ctx.Context().SetUserValue("dbConn", db)//    return ctx.Next()// })app.Post("api/register", register.Register(db))

登录后复制

以上就是数据库连接在第一个请求后关闭的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2485365.html

(0)
上一篇 2025年3月4日 21:44:58
下一篇 2025年2月23日 03:57:55

AD推荐 黄金广告位招租... 更多推荐

相关推荐

发表回复

登录后才能评论