在 Golang 结构体字段中保存类型

Siv*_*nBH 5 reflection struct go

我正在寻找一种方法来将类型(也许是reflection.Type?)作为自定义结构中的字段。其背后的原因是,我将 JSON 数组解码为稍后构建 SQL 查询的结构,但 JSON 数组中的整数、浮点数和时间戳是相同的,尽管在查询数据库时它们是不同的。这意味着我需要在查询之前将每个值转换为其正确的类型。

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

我希望的是这样的:

type Column struct {
    name string
    dataType type
}
someColumn := Column {name: "somecol", dataType: int}
convertedVal := SomeConversionFunc("5", someColumn.dataType)
Run Code Online (Sandbox Code Playgroud)

或者,这种事情也可以工作:

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

有任何想法吗?

eva*_*nal 5

我想你走在正确的道路上。在您的Column结构中您正在寻找reflect.Type. 你会得到的import "reflect"

如果您的列结构包含类型名称和值(作为原始字符串),您应该能够编写切换类型并为每种情况生成正确类型的值的方法。开关的简要参考在这里;https://golang.org/doc/ effective_go.html#switch

type Column struct {
    Name string
    DataType reflect.Type
    TypedValue interface{}
    StringValue string
}
Run Code Online (Sandbox Code Playgroud)

因为你说“但是 JSON 数组中的整数、浮点数和时间戳是相同的”,我假设 json 中的所有值在技术上都是字符串(意味着它们都被引用)。您可能不需要所有这些字段,但想法是将类型信息与属性名称和原始值结合起来。如果您使用 type 字段,interface{}您可以为其分配任何内容,这样您就可以轻松地在此结构的实例中保存原始 json 数据(名称和值)以及类型信息和合理 Go 类型中的值。


Siv*_*nBH 2

我尝试使用 @evanmcdonnal 提供的解决方案,但我找不到一种通用的方法来转换(这是从 json 数组中解组的任何数字的float64类型)到数据库中找到的任何数据类型(事实证明有点很棘手,因为不会将转换方法导出到,这相当于 Cassandra 的)。json.Unmarshaltimestampreflect.Valuetime.Timetimestamp

有效的是使用typeConversion字段而不是dataType字段,即保存一个函数,该函数从变量类型设置的类型转换为json.Unmarshal指定列的类型。

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

type Column struct {
    name string
    typeConversion func(reflect.Value) reflect.Value
}
Run Code Online (Sandbox Code Playgroud)

我已经拥有的一些 typeConversion 函数如下所示:

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()))
}
Run Code Online (Sandbox Code Playgroud)

这实际上恰好是一个非常好的解决方案,因为它非常通用:结构定义了任何转换函数的构建方式,这意味着我可以包装任何形式的转换以适合此 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()
Run Code Online (Sandbox Code Playgroud)