我需要在循环中对数据库进行SQL查询:
for rows.Next() {
fields, err := db.Query(.....)
if err != nil {
// ...
}
defer fields.Close()
// do something with `fields`
}
Run Code Online (Sandbox Code Playgroud)
什么会更好:保持原样或defer循环后移动:
for rows.Next() {
fields, err := db.Query(.....)
if err != nil {
// ...
}
// do something with `fields`
}
defer fields.Close()
Run Code Online (Sandbox Code Playgroud)
或者是其他东西 ?
icz*_*cza 39
延迟函数的执行不仅被延迟,延迟到周围函数返回的时刻,即使封闭函数突然终止(例如恐慌)也会执行.规格:推迟陈述:
"defer"语句调用一个函数,该函数的执行被推迟到周围函数返回的那一刻,因为周围的函数执行了一个return语句,到达了它的函数体的末尾,或者因为相应的goroutine是恐慌.
每当您创建一个值或资源提供正确关闭/处置它的方法时,您应该始终使用defer语句来确保它被释放,即使您的其他代码发生混乱以防止泄漏内存或其他系统资源.
确实,如果你在一个循环中分配资源,你不应该简单地使用defer,因为释放资源不会尽可能早地发生(在每次迭代结束时),只在for声明之后(仅在所有迭代之后) ).
你应该做的是,如果你有一个分配这些资源的代码片段,将它包装在一个函数中 - 无论是匿名函数还是命名函数 - 并且在你可能使用的函数中defer,资源将在它们为no时立即释放需要更长时间,重要的是即使您的代码中存在可能出现恐慌的错误.
例:
for rows.Next() {
func() {
fields, err := db.Query(...)
if err != nil {
// Handle error and return
return
}
defer fields.Close()
// do something with `fields`
}()
}
Run Code Online (Sandbox Code Playgroud)
或者如果放入命名函数:
func foo(rs *db.Rows) {
fields, err := db.Query(...)
if err != nil {
// Handle error and return
return
}
defer fields.Close()
// do something with `fields`
}
Run Code Online (Sandbox Code Playgroud)
并称之为:
for rows.Next() {
foo(rs)
}
Run Code Online (Sandbox Code Playgroud)
Adr*_*ian 35
整个问题defer是它在函数返回之前不会执行,所以在打开要关闭的资源之后立即放置它的适当位置.但是,由于你在循环中创建了资源,所以你根本不应该使用defer - 否则,你不会关闭循环中创建的任何资源,直到函数退出,所以它们会堆积到然后.相反,您应该在每次循环迭代结束时关闭它们,而不是 defer:
for rows.Next() {
fields, err := db.Query(.....)
if err != nil {
// ...
}
// do something with `fields`
fields.Close()
}
Run Code Online (Sandbox Code Playgroud)
可以构造一个局部函数来解决这个问题
for i := 0; i < 5; i++ {
func() {
f, err := os.Open("/path/to/file")
if err != nil {
log.Fatal(err)
} else {
defer f.Close()
}
}()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11216 次 |
| 最近记录: |