gpt4 book ai didi

golang sql/数据库在事务中准备语句

转载 作者:IT王子 更新时间:2023-10-29 02:11:15 24 4
gpt4 key购买 nike

当我在 golang SQL/数据库示例中阅读“事务”中“准备好的”语句的示例时。其中一行说“危险”,但提供的代码示例没有其他选择。

我想对以下查询有更清楚的解释,因为 Wiki 页面上提供的信息不多 - http://go-database-sql.org/prepared.html

tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
defer tx.Rollback()
stmt, err := tx.Prepare("INSERT INTO foo VALUES (?)")
if err != nil {
log.Fatal(err)
}
defer stmt.Close() // danger!
for i := 0; i < 10; i++ {
_, err = stmt.Exec(i)
if err != nil {
log.Fatal(err)
}
}
err = tx.Commit()
if err != nil {
log.Fatal(err)
}
// stmt.Close() runs here!

如果您在 defer stmt.Close() 中看到它提到,它很危险,但尚未注释掉以供用户删除它。

虽然我在上面的代码中没有看到任何问题,因为“defer”将在最后运行代码,但他们的意思是,上面的代码是错误的,应该用下面的代码或其他代码替换更好的替代代码。

tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
defer tx.Rollback()
stmt, err := tx.Prepare("INSERT INTO foo VALUES (?)")
if err != nil {
log.Fatal(err)
}
// Commented out below line.
// defer stmt.Close()
for i := 0; i < 10; i++ {
_, err = stmt.Exec(i)
if err != nil {
log.Fatal(err)
}
}
err = tx.Commit()
if err != nil {
log.Fatal(err)
}
// Comment removed from below line to close the stmt
stmt.Close()

我看不出上面两段代码有什么不同,但是,如果有任何不同或者我遗漏了什么,我需要专家的建议。

最佳答案

defer 语句是确保无论您如何退出函数都会运行的好方法。

在这种特殊情况下,这似乎无关紧要,因为所有错误处理程序都使用 log.Fatal。如果您将 log.Fatal 替换为 return 语句,并删除 defer,您现在必须在许多地方进行清理:

tx, err := db.Begin()
if err != nil {
return nil,err
}
stmt, err := tx.Prepare("INSERT INTO foo VALUES (?)")
if err != nil {
tx.Rollback()
return nil,err
}
defer
for i := 0; i < 10; i++ {
_, err = stmt.Exec(i)
if err != nil {
tx.Rollback()
return nil,err
}
}
err = tx.Commit()
if err != nil {
stmt.Close()
tx.Rollback()
return nil,err
}
stmt.Close()
return someValue, nil

如果你使用 defer,就很难忘记需要清理的地方。

关于golang sql/数据库在事务中准备语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46476388/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com