如何使用反射调用Golang中的Scan variadic函数? [英] How to call the Scan variadic function in Golang using reflection?

查看:592
本文介绍了如何使用反射调用Golang中的Scan variadic函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望调用 Rows.Scan()函数使用反射。但是它需要可变数量的指针,但我是新到Golang,并没有很多源示例。我需要使用反射,因为我打算用一个查询调用的值填充一个切片。所以基本上使用 rows.Columns()来获取行的长度,然后 make() code> [] interface {} 填充通常使用传递给 Scan()的指针填充的数据点函数。



基本上类似下面的代码:

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

任何人都有一个调用可变函数的例子,它使用反射来指针,我可以看看。



编辑:
示例代码似乎不会做我所做的。

  

import(
_github.com/lib/pq
database / sql
fmt

b
$ b func main(){

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

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

cols,_:= rows.Columns b
$ b for rows.Next(){

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

rows.Scan data ...)

fmt.Println(data)
}

}

结果:

  [< 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>]


解决方案

ve到达。它在遍历数据之前没有获取类型,因此不知道之前的每个值的类型,然后通过 Scan()拉出值,但是点真的是不必知道类型之前。



诀窍是创建2个切片,一个为值,并保存指针平行于值切片。然后,一旦指针被用于填充数据,值数组实际上用数据填充,然后可以用于填充其他数据结构。

  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;)

列,_:= rows.Columns ()
count:= len(columns)
values:= make([] interface {},count)
valuePtrs: b
for rows.Next(){

for i,_:= range columns {
valuePtrs [i] =& values [i]
}

rows.Scan(valuePtrs ...)

for i,col:= range columns {

var v interface {}

val:= values [i]

b,ok:= val。([] byte)

if(ok){
v = string b)
} else {
v = val
}

fmt.Println(col,v)
}
}
}


I'm looking to call the Rows.Scan() function using reflection. However it takes a variable number of pointers, but I'm new to Golang and 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>]

解决方案

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 {

            var v interface{}

            val := values[i]

            b, ok := val.([]byte)

            if (ok) {
                v = string(b)
            } else {
                v = val
            }

            fmt.Println(col, v)
        }
    }
}

这篇关于如何使用反射调用Golang中的Scan variadic函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆