当我读取golang SQL /数据库示例中“事务”中“Prepared”语句的示例时。其中一行表示“危险”,但代码示例没有提供替代方法。golang sql/database在事务中准备的语句
我想有下面的查询更加明确的解释,因为没有太多的信息,在提供Wiki页面上 - 如果你在defer stmt.Close()
它提到看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
”将在末尾运行代码,但这些代码是否意味着上述代码有误,应该用下面的代码或其他更好的替代代码替换。
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()
我看到上面两个码的没有什么区别,但是,我需要对上述专家的意见,如果有任何区别或如果我失去了一些东西。
可能是那个Close返回一个被忽略的错误。你的版本有同样的问题。你可以将close放在一个func中,以便更安全地使用延迟,或者在第二个版本中返回错误并检查tx的完整性。 – saarrrr
评论说延期在Go 1.4中很危险,但是很久以前就修复了这个问题。使用log.Fatal也是不幸的。我不确定我是否会用这个例子,你可以看看sql pkg的例子,虽然这些例子不包括准备好的语句https://golang.org/pkg/database/sql/#pkg-例子 –
是的,我不会使用'致命'。我会做一些像https://stackoverflow.com/a/46476451/2819754 –