我目前正在研究sqlite
数据库的一些代码。我注意到在准备查询之后,我总是需要在退出函数之前完成查询(sqlite3_finalize(statementPointer)
)。除了填补所有可能性之外,有没有办法做到这一点?
例如:
func updateColumn(db: COpaquePointer, name: String, x: sqlite3_int64, y: String!=nil) -> Bool {
var statement = "UPDATE MY_TABLE SET X=?"
var statementPointer: COpaquePointer = nil
if y != nil {
statement += ", Y=?"
}
statement += " WHERE NAME=?"
if sqlite3_prepare_v2(db, statement, -1, &statementPointer, nil) != SQLITE_OK {
return false
} else if sqlite3_bind_int64(statementPointer, 1, x) != SQLITE_OK {
// Note this code here
sqlite3_finalize(statementPointer)
return false
}
if y != nil {
if sqlite3_bind_text(statementPointer, 2, y, -1, nil) != SQLITE_OK {
// Note this repetition
sqlite3_finalize(statementPointer)
return false
}
}
if sqlite3_step(statementPointer) != SQLITE_DONE {
// Note this repetition
sqlite3_finalize(statementPointer)
return false
}
// Note this repetition
sqlite3_finalize(statementPointer)
return true
}
当然,这只是我提出来解释这一点。在实际代码中,还有许多其他if
条款,我需要完成它们的陈述。
我知道这对于swift中的类来说就像deinit
,但是函数也有deinit
吗?
例如(我希望它的代码类似但不起作用的代码):
func updateColumn(params...) -> Bool {
// code...
deinit {
sqlite3_finalize(statementPointer)
}
}
答案 0 :(得分:9)
是的,有一个“deinit for functions” - 它被称为defer
:
defer
语句用于在将defer
语句出现的范围之外的程序控制转移之前执行代码。
请注意,与您的假设示例不同,defer
语句必须在之前出现,否则可能会导致执行清理,而不是在封闭范围的末尾。一般来说,它的工作原理如下:
func doStuff() {
let resource = acquireResource()
defer {
cleanup(resource)
}
if something { return }
doOtherStuff()
}
此处,无论函数是由cleanup(resource)
退出还是因为它到达其范围的末尾(if something
之后),都会调用doOtherStuff()
。
你不能像你要求的那样将defer
置于if
内 - 它只会延迟它所在范围的退出,所以它会在结束时执行if
身体。但是defer
确实与guard
很好地构成...在你的情况下,你可能想要这样的东西:
func updateColumn(db: COpaquePointer, name: String, x: sqlite3_int64, y: String!=nil) -> Bool {
var statementPointer: COpaquePointer = nil
//... Other stuff...
guard sqlite3_prepare_v2(db, statement, -1, &statementPointer, nil) == SQLITE_OK
else { return false }
// after this you want any possible exit to do finalize, so put the defer here
defer { sqlite3_finalize(statementPointer) }
// every `return` after here, true or false, will execute the `defer` clause
guard sqlite3_bind_int64(statementPointer, 1, x) == SQLITE_OK
else { return false }
guard y != nil && sqlite3_bind_text(statementPointer, 2, y, -1, nil) == SQLITE_OK
else { return false }
guard sqlite3_step(statementPointer) == SQLITE_DONE
else { return false }
return true
}
答案 1 :(得分:1)
如何使用defer关键字。
func updateColumn(params...) -> Bool {
// code...
defer {
sqlite3_finalize(statementPointer)
}
}