我是 Go 的新手,而不是 sql 中最好的。
我的資料庫中有一個簡單的表,其中包含用戶名。我將 SAM、名字和姓氏存盤在表中。當我現在嘗試更改資料庫中的某些內容時,出現錯誤database is locked。那是我的代碼:
func createNewUser(w http.ResponseWriter, r *http.Request) {
var user User
err := decodeJSONBody(w, r, &user)
if checkError(w, err) {
return
}
rows, err := mainDB.Query("SELECT * FROM users WHERE SAM = ?", user.Sam)
if checkError(w, err) {
return
}
defer rows.Close()
if rows.Next() {
http.Error(w, "User already exists", http.StatusConflict)
return
}
_, err = mainDB.Exec("INSERT INTO users (SAM, Vorname, Nachname) VALUES (?, ?, ?)", user.Sam, user.Vorname, user.Nachname)
if checkError(w, err) {
return
}
json.NewEncoder(w).Encode(user)
}
decodeJSONBody和checkError作業和資料庫無關。據我所知,rows.Close應該關閉列,以便我可以寫回
uj5u.com熱心網友回復:
根據評論 SQLite在鎖定/并發方面有一些限制,這意味著您在并發運行多個陳述句時需要小心。不幸的是,我在發表評論時沒有詳細審查您的代碼,因此盡管看似解決了問題,但它是錯誤的。
你添加了一個defer rows.Close(); 這將釋放用于運行查詢的資料庫連接,但由于defer,這只會在周圍函式回傳時發生。通常這不是什么大問題,因為遍歷整個結果集會自動關閉rows. 檔案指出:
如果呼叫 Next 并回傳 false 并且沒有進一步的結果集,則 Rows 將自動關閉,只需檢查 Err 的結果即可。
在您的代碼中,如果rows.Next()為真,您會回傳:
if rows.Next() {
http.Error(w, "User already exists", http.StatusConflict)
return
}
這意味著rows.Close()不需要添加額外的東西。但是,正如您所說的“多次添加 rows.Close(),現在它可以作業了”,我懷疑您的完整代碼可能比所提供的代碼復雜一些(并且rows.Close()需要添加其中的一個)。
因此rows.Close()不需要添加額外的呼叫;它不會導致問題(除了不必要的函式呼叫)。但是,您應該檢查錯誤:
rows, err := mainDB.Query("SELECT * FROM users WHERE SAM = ?", user.Sam)
if checkError(w, err) {
rows.Close()
return
}
if rows.Next() {
http.Error(w, "User already exists", http.StatusConflict)
return
}
if err = rows.Err(); err != nil {
return // It's worth checking fort an error here
}
請注意,go-sqlite3的常見問題解答包含有關處理“錯誤:資料庫已鎖定”的資訊(值得確保您遵循建議)。
注意2:考慮使用EXISTS而不是運行查詢然后嘗試獲取一行 - 它可能會更快并且允許您使用QueryRow它來簡化您的代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/365604.html
