我正在编写一些实用程序,以使用 Go 以通用方式从 BigQuery 检索多行。 例如
type User struct {name string, surname string}
type Car struct {model string, platenumber string}
query1:="SELECT name, surname FROM UserTable"
query2:="SELECT model, platenumber FROM CarTable"
cars, _ := query2.GetResults()
users, _ := query1.GetResults()
OR
cars := []Car{}
query2.GetResults(cars) // and it would append to the slice
我不确定
GetResults
的签名。我需要以某种方式将类型传递给 BigQuery 库,以便它可以检索数据并将其正确映射到结构。但同时我需要使其通用,以便它可以用于不同类型。
目前我的
GetResults
看起来像这样:它不起作用,错误是:
bigquery:无法将 *interface {} 转换为 ValueLoader(需要指向 []Value、map[string]Value 或 struct 的指针)[]
但是我不能直接传递该结构,因为我想使其通用。
func (s *Query) GetResults() ([]interface{}, error) {
var result []interface{}
job, err := s.Run()
if err != nil {
s.log.Error(err, "error in running the query")
return nil, err
}
it, err := job.ReadData()
if err != nil {
s.log.Error(err, "error in reading the data")
return nil, err
}
var row interface{}
for {
err := it.Next(&row)
if err != nil {
fmt.Print(err)
break
}
result = append(result, row)
}
return result, nil
}
还有其他方法可以实现这一目标吗?或者不创建这样的方法是好方法吗?
我已经尝试了很多不同的事情,有或没有指针,有或没有数组,通过修改参数,或返回一个新列表,似乎没有任何效果,并且就性质而言,做所有这些感觉有点错误我想要实现的目标“简单”。
我还考虑过执行以下操作
GetResults[T any]() ([]T, error)
但它被“排除”,因为
GetResults
是接口的一部分(并且我们不能为接口的方法定义泛型)。我不能/不想为所有接口定义类型,因为它会影响其他接口。
基本上
bigquery.Value
是 interface{}
的基础,因此您可以使用它,在代码中将 interface{}
替换为 bigquery.Value
。
这是我的代码的示例:
func (srv *SBigQuery) GBQReadQueryToStruct(ctx context.Context, query string) ([]map[string]bigquery.Value, error) {
var results []map[string]bigquery.Value
// Construct a query.
q := srv.Query(query)
// Execute the query.
it, err := q.Read(ctx)
if err != nil {
return nil, fmt.Errorf("unable to read query: %v", err)
}
// Iterate through the results.
var row map[string]bigquery.Value
for {
err := it.Next(&row)
if err == iterator.Done {
break
}
if err != nil {
return nil, fmt.Errorf("unable to iterate through query results: %v", err)
}
results = append(results, row)
}
return results, nil
}
参考: