在Go语言中关闭数据库连接的更好/更简洁的方法是什么?

huangapple go评论79阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2015年1月21日 10:19:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/28058534.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定