文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-02-06 11:15

关注

问题内容

我在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}\n",
    }))

    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))

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 资料下载
  • 历年真题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯