Reflection 在Golang结构字段中保留类型

Reflection 在Golang结构字段中保留类型,reflection,struct,go,Reflection,Struct,Go,我正在寻找一种将类型(可能是reflection.type?)作为字段保存在自定义结构中的方法。这背后的原因是,我正在将JSON数组解码为结构,然后从中构建SQL查询,但在JSON数组中,int、float和timestamp是相同的,尽管在查询数据库时它们是不同的。这意味着我需要在查询之前将每个值转换为正确的类型 我认为答案就在reflect包的某个地方,但我还没有弄清楚如何利用它 我希望是这样的: type Column struct { name string dataTy

我正在寻找一种将类型(可能是reflection.type?)作为字段保存在自定义结构中的方法。这背后的原因是,我正在将JSON数组解码为结构,然后从中构建SQL查询,但在JSON数组中,int、float和timestamp是相同的,尽管在查询数据库时它们是不同的。这意味着我需要在查询之前将每个值转换为正确的类型

我认为答案就在reflect包的某个地方,但我还没有弄清楚如何利用它

我希望是这样的:

type Column struct {
    name string
    dataType type
}
someColumn := Column {name: "somecol", dataType: int}
convertedVal := SomeConversionFunc("5", someColumn.dataType)
type Column struct {
    name string
    typeConversion func(reflect.Value) reflect.Value
}
func floatToTime(varFloat reflect.Value) reflect.Value {
    timestamp := time.Unix(int64(varFloat.Float()), 0)
    return reflect.ValueOf(timestamp)
}

func floatToInt(varFloat reflect.Value) reflect.Value {
    return reflect.ValueOf(int(varFloat.Float()))
}
或者,这类事情也可以奏效:

type Column struct {
    name string
    dataType func()
}
someColumn := Column {name: "somecol", dataType: ConvertToInt}
convertedVal := someColumn.dataType("5")

有什么想法吗?

我想你的思路是对的。在您要查找的
结构中,键入。通过
import“reflect”
,您将获得该功能

如果列结构包含类型名称和值(作为原始字符串),则应该能够编写打开类型并为每种情况生成正确类型的值的方法。此处为开关的简要参考


因为您说过“但是int、float和timestamp在JSON数组中是相同的”,所以我假设JSON中的所有值在技术上都是字符串(这意味着它们都被引用)。您可能不需要所有这些字段,但其思想是将类型信息与属性名称和原始值结合起来。如果使用类型为
interface{}
的字段,则可以为其分配任何内容,以便保存原始json数据(名称和值)以及该结构实例中的类型信息和合理Go类型中的值。我尝试使用@evanmcdonnal提供的解决方案,但找不到转换
float64
(即类型
json.Unmarshal
给它从json数组中解组的任何数字的方法)对于数据库中找到的任何数据类型(
timestamp
证明有点棘手,因为
reflect.Value
没有将转换方法导出到
time.time
,这相当于Cassandra的
timestamp

工作原理是使用
typeConversion
字段而不是
dataType
字段,也就是说,持有一个从类型
json转换为distined列类型的函数。Unmarshal
将变量的类型设置为

因此,我的结构如下所示:

type Column struct {
    name string
    dataType type
}
someColumn := Column {name: "somecol", dataType: int}
convertedVal := SomeConversionFunc("5", someColumn.dataType)
type Column struct {
    name string
    typeConversion func(reflect.Value) reflect.Value
}
func floatToTime(varFloat reflect.Value) reflect.Value {
    timestamp := time.Unix(int64(varFloat.Float()), 0)
    return reflect.ValueOf(timestamp)
}

func floatToInt(varFloat reflect.Value) reflect.Value {
    return reflect.ValueOf(int(varFloat.Float()))
}
我已有的一些类型转换函数如下所示:

type Column struct {
    name string
    dataType type
}
someColumn := Column {name: "somecol", dataType: int}
convertedVal := SomeConversionFunc("5", someColumn.dataType)
type Column struct {
    name string
    typeConversion func(reflect.Value) reflect.Value
}
func floatToTime(varFloat reflect.Value) reflect.Value {
    timestamp := time.Unix(int64(varFloat.Float()), 0)
    return reflect.ValueOf(timestamp)
}

func floatToInt(varFloat reflect.Value) reflect.Value {
    return reflect.ValueOf(int(varFloat.Float()))
}
这实际上是一个非常好的解决方案,因为它非常通用:结构定义了任何转换函数的构建方式,这意味着我可以包装任何形式的转换以适应此API,并且因为返回值总是
reflect.value
,通过调用
Interface()
,我可以使用正确的类型访问基础值,如下所示:

// value is the data unmarshaled by json
// I convert it to reflect.Value, then convert it again using my custom typeConversion
// Then  I use Interface() to get the final value in the final (and column-appropriate) type
column.typeConversion(reflect.ValueOf(value)).Interface()
报告应有助于:

type Table struct {
    age int `sql:"type:int;`
    price float `sql:"type:float;`
}

对不起,我不太明白。
dataType
字段是字符串还是
reflect.Type
?如果它是一个
reflect.Type
,那么如何输入一个int类型,例如?如果是字符串,是否有一个函数可以使用字符串转换为所需的类型?@SivanBH
dataType
应该是
reflect.type
。对于任何实例
i
(任何类型),您都可以使用
reflect.TypeOf
获取其类型。我将用我认为更合理的模型样本进行编辑。我将导出所有字段,您可以根据需要进行更改。这也是我所能做到的,但似乎不起作用。例如,如果
数据类型
应该是int,我使用
reflect.int
,但这实际上不是
reflect.Type
,而是
reflect.Kind
。无论哪种方式,reflect提供的转换方法都只能作为
reflect.Value
实现的方法使用。我这里缺少什么?似乎你需要一个ORM包。我不确定这是解决方案。所有内容都被解码为字符串,这意味着我需要将这些字符串转换为相应列的数据类型,然后再将其传递给查询生成器(我使用squirrel创建Cassandra查询-CQL),这是一个有趣的解决方案,我还没有遇到过。但它不适合我的需要,因为我使用映射来表示用户请求的列到值。这使我走上了正确的道路。我有一个reflect.type类型的结构成员,并给它赋值reflect.TypeOf(variable)。