dongnai3960 2013-07-24 22:06
浏览 58
已采纳

如何使用反射调用扫描可变参数函数

I'm looking to call the Rows.Scan() function using reflection. However it takes a variable number of pointers, but there are not a lot of source examples. I need to use reflection because I plan on filling a slice with the values from a Query call. So basically using rows.Columns() to get the length of the row and then make() a slice of []interface{} to fill with the data points that would normally be filled using the pointers passed to the Scan() function.

Basically something like this code:

col := rows.Columns()
vals := make([]interface{}, len(cols))
rows.Scan(&vals)

Anyone have an example of calling a variadic function that takes pointers using reflection that I can take a look at?

Edit: Sample code that doesn't appear to do what I'm after.

package main

import (
    _ "github.com/lib/pq"
    "database/sql"
    "fmt"
)


func main() {

    db, _ := sql.Open(
        "postgres",
        "user=postgres dbname=Go_Testing password=ssap sslmode=disable")

    rows, _ := db.Query("SELECT * FROM _users;")

    cols, _ := rows.Columns()

    for rows.Next() {

        data := make([]interface{}, len(cols))

        rows.Scan(data...)

        fmt.Println(data)
    }

}

The results:

[<nil> <nil> <nil> <nil> <nil>]
[<nil> <nil> <nil> <nil> <nil>]
[<nil> <nil> <nil> <nil> <nil>]
[<nil> <nil> <nil> <nil> <nil>]
[<nil> <nil> <nil> <nil> <nil>]
[<nil> <nil> <nil> <nil> <nil>]
  • 写回答

4条回答 默认 最新

  • donglian6625 2013-07-26 15:43
    关注

    Here's the solution that I've arrived at. It doesn't get the Types before traversing the data, and so doesn't know before hand the type of each value before pulling the values out through Scan(), but the point really is to not have to know the types before hand.

    The trick was to create 2 slices, one for the values, and one that holds pointers in parallel to the values slice. Then once the pointers are used to fill data, the values array is actually filled with the data, which can then be used to populate other data structures.

    package main
    
    import (
        "fmt"
        _ "github.com/lib/pq"
        "database/sql"
    )
    
    func main() {
        db, _ := sql.Open(
            "postgres",
            "user=postgres dbname=go_testing password=pass sslmode=disable")
    
        rows, _ := db.Query("SELECT * FROM _user;")
    
        columns, _ := rows.Columns()
        count := len(columns)
        values := make([]interface{}, count)
        valuePtrs := make([]interface{}, count)
    
        for rows.Next() {
            for i := range columns {
                valuePtrs[i] = &values[i]
            }
    
            rows.Scan(valuePtrs...)
    
            for i, col := range columns {
                val := values[i]
    
                b, ok := val.([]byte)
                var v interface{}
                if (ok) {
                    v = string(b)
                } else {
                    v = val
                }
    
                fmt.Println(col, v)
            }
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 vs2022无法联网
  • ¥15 TCP的客户端和服务器的互联
  • ¥15 VB.NET操作免驱摄像头
  • ¥15 笔记本上移动热点开关状态查询
  • ¥85 类鸟群Boids——仿真鸟群避障的相关问题
  • ¥15 CFEDEM自带算例错误,如何解决?
  • ¥15 有没有会使用flac3d软件的家人
  • ¥20 360摄像头无法解绑使用,请教解绑当前账号绑定问题,
  • ¥15 docker实践项目
  • ¥15 利用pthon计算薄膜结构的光导纳