本文介绍了事务中的golang sql/database准备好的语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然我正在阅读golang SQL/数据库示例中事务"中的准备"语句示例.其中一行说危险",但是提供的代码示例没有其他选择.

While I was reading the example of "Prepared" statement in "transaction" in golang SQL/database example. One of the line says, "danger", yet the code example was provided without an alternative.

我想对下面的查询有更清晰的解释,因为Wiki页上的- http://go-database-sql.org/prepared.html

I wanted to have more clear explanation on below query, as not much information was provided on Wiki page at - 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()中看到它提到的话,这很危险,但尚未注释掉以供用户删除.

If you see in defer stmt.Close() it mentions, it's dangerous and yet not commented out for users to remove it.

尽管我在上面的代码中没有看到任何问题,因为" defer "将在最后运行代码,但这是否意味着,上面的代码是错误的,应将其替换为下面的代码或其他代码更好的替代代码.

Though I see no issue in above code as "defer" is going to run the code at the end but do they mean, above code is wrong and it should be replaced with below code or other better alternatives code.

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

我认为上面的两个代码没有什么区别,但是,如果有任何区别或缺少某些内容,我需要上面的专家建议.

I see no difference in both of the code above, yet, I need expert advice on above if there is any difference or If I am missing something.

推荐答案

defer 语句是一种确保无论您如何退出函数都能正常运行的好方法.

a defer statement is a good way to make sure something runs no matter how you exit the function.

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

In this particular case, it seems to not matter, since all the error handlers use log.Fatal. If you replace the log.Fatals with return statements, and remove the defers, you now have to cleanup in many places:

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,则很难忘记需要清理的一个地方.

If you use defer, it is harder to forget one place you need to clean something up.

这篇关于事务中的golang sql/database准备好的语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 02:30