Golang服务器:使用具有可变列数的SQL查询结果发送JSON

时间:2016-02-24 14:41:15

标签: sql json go

我正在使用Go服务器创建一个RESTful API的小实现。

我从网址中提取查询参数(我知道它不安全,我稍后会尝试修复此问题,但如果您对此主题有任何建议,那么它们将是有用)。

我有3个sring变量保存的表名,所需列和一些条件。 我正在使用此查询:

rows, _ := db.Query(fmt.Sprintf("SELECT %s FROM %s WHERE %s", columns, table, conditions))

我想将查询结果作为JSON发送回我的前端。我有不同数量的未知列,所以我不能这样做"标准"办法。 我能想到的一个解决方案是构建一个JSON字符串"手动"来自查询结果和rows.Columns()。

但是我希望以更加软化的方式使用类似可变界面和类似的东西来做这件事。问题是,即使尝试了很多,我仍然不明白它是如何工作的。

我尝试使用以下代码

cols, err := rows.Columns()             // Get the column names; remember to check err
vals := make([]sql.RawBytes, len(cols)) // Allocate enough values
ints := make([]interface{}, len(cols))  // Make a slice of []interface{}
for i := range ints {
    vals[i] = &ints[i] // Copy references into the slice
}
for rows.Next() {
    err := rows.Scan(vals...)
    // Now you can check each element of vals for nil-ness,
    // and you can use type introspection and type assertions
    // to fetch the column into a typed variable.
}

来自this tutorial,但它不起作用,我收到错误

cannot use &ints[i] (type *interface {}) as type sql.RawBytes in assignment

即使它起作用,我也不理解。

有没有人有这个好的解决方案?一些解释也很好。

非常感谢。

1 个答案:

答案 0 :(得分:3)

第一个问题在这里:

for i := range ints { vals[i] = &ints[i] // Copy references into the slice }

这是您将RawBytes的值设置为接口的指针。

在我解释这是什么意思之前,我会先看看能解释一下这个概念是什么。

所以通常在Go中获取SQL的响应时,你会得到每个列和类型的切片(id int,name string,...),这样你就可以将每条SQL记录读入这个切片,每列都会被映射到相同类型的值。

对于像你这样的情况,你会在SQL的响应中有更多种类,并且需要Go来处理它,你会这样做:

for i := range ints { ints[i] = &vals[i] // Copy references into the slice }

这就是说,每个interface值都包含指向vals数组的指针,该数组将保存来自SQL的响应。 (在我的例子中,我使用[] [] byte而不是RawBytes,因此vals中的值将是来自SQL的一个字节值片段。)

然后你会这样做:

err := rows.Scan(ints...)

由于interface可以计算任何类型,当ints数组被填充时,它将接受任何值,然后根据指针更新vals数组中的位置,其中SQL的值为RawBytes类型

HTH