登录
首页 >  Golang >  Go问答

Golang SQL rows.Scan函数用于处理所有字段的泛型类型

来源:stackoverflow

时间:2024-03-23 22:12:38 171浏览 收藏

Go 语言的 `sql.Rows.Scan` 函数用于从查询结果中获取数据,通常需要为每个字段提供明确的引用。本文探讨如何使用泛型类型 `r` 来替代这种方法,从而实现对不同结构类型结果的通用处理。作者建议使用提供任意结构扫描功能的包,如 `sqlx`,以避免反射带来的性能开销。

问题内容

我想使用 sql 包中的 scan() 函数来执行可能(或不)返回多行的 select 语句,并在我的函数中返回这些结果。

我是 golang 泛型的新手,并且对如何实现这一目标感到困惑。 通常,我们会在 *sql.rows 上使用 scan 函数,并提供对我们想要读取行的预期“结果类型”的所有字段的引用,例如:

var alb album
rows.scan(&alb.id, &alb.title, &alb.artist,
            &alb.price, &alb.quantity)

其中album 是一个结构类型,其中显示了这五个字段。

现在,为了不为我拥有的每个 sql 表编写类似的函数 n 次,我想使用泛型类型r来代替。 r 是通用接口类型 result,我将这种类型定义为 n 个不同结构之一:

type Result interface {
    StructA | StructB | StructC
}

func ExecSelect[R Result](conn *sql.DB, cmd Command, template R) []R

我现在如何编写 rows.scan(...) 以将 scan 操作应用于我的 r 具体类型结构的所有字段?例如我想要 rows.scan(&res.field1, &res.field2, ...) 其中 res 是 r 类型,并且 scan 应该接收我当前具体类型 r 的所有字段。我实际上需要提供一个'template' 作为 r 具体类型的参数,以便在运行时清楚哪个结构现在是相关的?

请纠正我在考虑泛型时所犯的任何错误。


正确答案


对于泛型来说,这是一个糟糕的用例。

函数 sql.Rows.Scan 的参数应该是扫描目标,即您的结构字段,结果集中的每一列都有一个,并且在通用函数体中,您的 R 类型参数为 do not have access to the fields

即使您这样做了,您的 Result 约束中的结构也可能具有不同的字段...?那么,您如何设想编写适用于不同字段的通用代码?

您可能会使用提供任意结构扫描(如 sqlx )和 StructScan 等功能的包来完成您想要的任务,但它在幕后使用反射将结构字段映射到 sql.Rows.Scan 参数,因此您不会得到任何结果仿制药完全有好处。

如果有的话,那就是让情况变得更糟,因为现在使用类型参数会带来额外的性能开销。

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>