如何获得字段类型的零值 [英] How to get zero value of a field type

查看:64
本文介绍了如何获得字段类型的零值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含许多字段的结构-我想出了如何使用反射提取字段名称,值和标记信息的方法.我还要做的就是确定某个字段的值是否与该字段的默认值不同.

I have a struct containing many fields - I've figured out how to extract the field name, value, and tag information using reflection. What I also want to do is to determine if the value of a field is different from the field's default value.

目前,我有这个(有效,但有点臭):

Currently, I have this (works, but a bit smelly):

...
qsMap := make(map[string]interface{})
var defaultTime time.Time
var defaultString string
...
// get the field name and value
fieldName := s.Type().Field(i).Tag.Get("bson")
fieldValue := valueField.Interface()

// use reflection to determine the TYPE of the field and apply the proper formatting
switch fieldValue.(type) {
case time.Time:
if fieldValue != defaultTime {
    qsMap[fieldName] = fieldValue
}
case string:
if fieldValue != defaultString {
    qsMap[fieldName] = fieldValue
}
...
}

在我看来,在这种情况下应该有一种避免类型切换的方法-我正在尝试做的是建立一个字段/值的映射,该字段的值与其默认零值不同,例如:

Seems to me that there should be a way to avoid the type switch in this case - what I'm trying to do is build up a map of field/values that have a value different from their default zero value, something like:

// doesn't work -- i.e., if fieldValue of type string would be compared against "", etc.
if fieldValue != reflect.Zero(reflect.Type(fieldValue)) {
    qsMap[fieldName] = fieldValue
}

是否有一种优雅的方式来实现这一目标?

Is there an elegant way to accomplish this?

谢谢!

推荐答案

对于支持相等操作的类型,您可以只比较包含零值和字段值的 interface {} 变量.像这样:

For types that support the equality operation, you can just compare interface{} variables holding the zero value and field value. Something like this:

v.Interface() == reflect.Zero(v.Type()).Interface()

尽管对于函数,映射和切片,此比较将失败,因此我们仍然需要包括一些特殊的大小写.此外,尽管数组和结构是可比较的,但如果它们包含不可比较的类型,则比较将失败.所以您可能需要类似的东西:

For functions, maps and slices though, this comparison will fail, so we still need to include some special casing. Further more, while arrays and structs are comparable, the comparison will fail if they contain non-comparable types. So you probably need something like:

func isZero(v reflect.Value) bool {
    switch v.Kind() {
    case reflect.Func, reflect.Map, reflect.Slice:
        return v.IsNil()
    case reflect.Array:
        z := true
        for i := 0; i < v.Len(); i++ {
            z = z && isZero(v.Index(i))
        }
        return z
    case reflect.Struct:
        z := true
        for i := 0; i < v.NumField(); i++ {
            z = z && isZero(v.Field(i))
        }
        return z
    }
    // Compare other types directly:
    z := reflect.Zero(v.Type())
    return v.Interface() == z.Interface()
}

这篇关于如何获得字段类型的零值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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