英文:
Better/shorter way to close database connection in Go
问题
通常我会这样写:
rows := db.MyPgConn.QueryRows(`SELECT * FROM bla`) // 或者任何其他查询
for rows.Next() { // 如果有结果
// rows.Scan(
// 进行自定义操作
}
rows.Close() // 关闭记录集
但是这种方式存在可能忘记写rows.Close()
的情况,就像这个代码一样,可能会导致可用连接/套接字的数量减少,有没有更好的方法来处理这个问题?
英文:
Usually I write something like this
rows := db.MyPgConn.QueryRows(`SELECT * FROM bla`) // or any other query
for rows.Next() { // if there are result
// rows.Scan(
// do custom operation
}
rows.Close() // close recordset
But that way, there are possibility that I forgot to write rows.Close()
just like this code that could make the number of available connection/socket depleted, is there better way to do this?
答案1
得分: 6
Go为了这个目的引入了defer
。
rows := db.MyPgConn.QueryRows(`SELECT * FROM bla`) // 或者任何其他查询
defer rows.Close()
for rows.Next() { // 如果有结果
// rows.Scan(
// 进行自定义操作
}
从文档中可以看到:
延迟调用
Close
等函数有两个优点。首先,它保证你永远不会忘记关闭文件,如果以后编辑函数添加新的返回路径,这是一个容易犯的错误。其次,它意味着关闭的位置靠近打开的位置,这比将其放在函数末尾要清晰得多。
英文:
Go introduced defer
exactly for this purpose.
rows := db.MyPgConn.QueryRows(`SELECT * FROM bla`) // or any other query
defer rows.Close()
for rows.Next() { // if there are result
// rows.Scan(
// do custom operation
}
From the documentation:
> Deferring a call to a function such as Close
has two advantages. First, it guarantees that you will never forget to close the file, a mistake that's easy to make if you later edit the function to add a new return path. Second, it means that the close sits near the open, which is much clearer than placing it at the end of the function.
答案2
得分: 2
如Intermernet所提到的,defer语句是将close语句放在rows变量声明的附近的最佳方法。我能想到的唯一可能使这个过程更短或更容易的方法是在数据库调用周围创建一个包装函数。
func performQuery(q string, op func(db.rows)) {
rows := db.MyPg.Conn.QueryRows(q)
// defer rows.Close()
op(rows)
rows.Close()
}
// 然后我们可以这样做:
performQuery(`SELECT * FROM bla`,func(rows db.Rows) {
for rows.Next() {
// rows.Scan(
}
})
然而,这样做将限制您使用带参数的查询(例如SELECT * FROM tableName WHERE id = $1
)。
英文:
As mentioned by Intermernet, the defer statement is the best way to get the close statement closer to where the rows var is declared. The only way I can think of that might make this shorter or easier would be to create a wrapper function around your database call.
func performQuery(q string, op func(db.rows)) {
rows := db.MyPg.Conn.QueryRows(q)
// defer rows.Close()
op(rows)
rows.Close()
}
// then we could do:
performQuery(`SELECT * FROM bla`,func(rows db.Rows) {
for rows.Next() {
// rows.Scan(
}
})
This however would limit you from making queries with parameters (for example SELECT * FROM tableName WHERE id = $1
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论