Reuse or copy *sql.Rows in Golang

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

Reuse or copy *sql.Rows in Golang

问题

*sql.Rows 是一个结果集的迭代器,它在迭代过程中会不断地从数据库中获取下一行数据。一旦迭代完成,*sql.Rows 就会被标记为已关闭,不能再使用。

如果你想在迭代完成后将 *sql.Rows 传递给另一个函数使用,你可以将结果集的数据存储在一个切片或其他数据结构中,然后将该数据结构传递给另一个函数。

以下是一个示例代码:

rows, err := db.Query(...)
if err != nil {
    // 错误处理
}

defer rows.Close()

var data []YourStruct // YourStruct 是你自定义的结构体类型

for rows.Next() {
    var row YourStruct
    err := rows.Scan(&row.Field1, &row.Field2) // 假设你的结构体有两个字段 Field1 和 Field2
    if err != nil {
        // 错误处理
    }

    data = append(data, row)
}

if err := rows.Err(); err != nil {
    // 错误处理
}

anotherFunction(data) // 将数据传递给另一个函数进行处理

在这个示例中,我们使用一个切片 data 来存储结果集的数据。在迭代过程中,我们将每一行数据存储在一个结构体 YourStruct 中,并将该结构体添加到切片中。迭代完成后,我们将整个切片传递给 anotherFunction 进行处理。

请注意,在使用完 *sql.Rows 后,我们使用 defer rows.Close() 来确保结果集被正确关闭,以释放相关资源。

英文:

Is it possible to reuse the same *sql.Rows after the *sql.Rows.Next() was called so I could pass it to another function?

rows, err := db.Query(...)
for rows.Next() {
    // rows.Scan()
}
anotherFunction(rows) // NOT WORKING: This rows became empty.

I tried to make another copy of the *sql.Rows but it didn't work.

rows, err := db.Query(...)
anotherRows := *rows
// PANIC: call of load copies lock value: database/sql.Rows contains sync.RWMutex

答案1

得分: 3

database/sql包在读取完Rows后没有提供任何重置(rewind)Rows的方法,也就是说它是一个“只能向前”的结果集。

此外,它会在内部保持与底层(物理)数据库连接的链接,因此复制或传递它是一个不好的主意。

如果你需要对数据应用多个函数,只需使用Scan方法读取所有的行,得到一个数据对象的切片,然后将其传递给其他函数。

Scan方法会复制你读取的数据:

Scan将匹配的行的列复制到dest指向的值中。

因此,你可以安全地关闭Rows对象(释放任何相关的数据库资源)。

在执行查询后(err)和读取行后,你还应该注意错误,可以通过rows.Err()来获取。

英文:

The database/sql package does not provide any means to rewind the Rows, after you have read them, i.e. it is a "forward only" result set.

Moreover, it will maintain a link to the underlying (physical) database connection, inside it, making it a bad idea to copy it or pass it around.

If you need to apply multiple functions to your data, just Scan all the rows, to get a slice of data objects, and then pass this around.

Scan will make a copy of the data you read:

>Scan copies the columns from the matched row into the values pointed at by dest.

so you can then safely Close your Rows object (releasing any associated database resources).

You should watch out for errors too, after executing the Query (err) and after reading the rows, via rows.Err().

huangapple
  • 本文由 发表于 2017年7月3日 15:01:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/44879548.html
匿名

发表评论

匿名网友

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

确定