當我讀取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 –