How to find the empty field in struct using reflect?

How to find the empty field in struct using reflect?
i want convert struct to map type, and only add the valid field to map.

type PlaceDoc struct {
	Loc [2]float64
	First_time time.Time
	Last_time time.Time
	Dev_id string
	Geo_hash string
}

func (mdo *DocDbMongoOptSelection)GetDocToDBArgument(doc interface{})interface{} {
	m := make(map[string]interface{})
	s := reflect.TypeOf(doc)
	for i:= s.NumField() - 1; i >= 0 ; i-- {
		n := s.Field(i).Name
		e := reflect.ValueOf(doc).Field(i)
		if !e.IsValid(){
			continue
		}
		fmt.Println(n, "|", e)
	}
	return m
} 

i only set dev_id field, but all field is Valid…

i use kind() to check the value type and then compare with the nil value of that value type,

func IsEmptyValue(e reflect.Value) bool {
is_show_checking := false
var checking_type string
is_empty := true
switch e.Type().Kind(){
case reflect.String:
    checking_type = "string"
    if e.String() != "" {
        // fmt.Println("Empty string")
        is_empty = false
    }
case reflect.Array:
    checking_type = "array"
    for j:=e.Len() - 1 ; j>=0; j-- {
        is_empty = IsEmptyValue(e.Index(j))
        if is_empty == false {
            break
        }
        /*if e.Index(j).Float() != 0 {
            // fmt.Println("Empty float")
            is_empty = false
            break
        }*/
    }
case reflect.Float32, reflect.Float64:
    checking_type = "float"
    if e.Float() != 0{
        is_empty = false
    }
case reflect.Int32, reflect.Int64:
    checking_type = "int"
    if e.Int() != 0{
        is_empty = false

    }
case reflect.Ptr:
    checking_type = "Ptr"
    if e.Pointer() != 0 {
        is_empty = false
    }
case reflect.Struct:
    checking_type = "struct"
    for i:=e.NumField()-1;i>=0;i--{
        is_empty = IsEmptyValue(e.Field(i))
        // fmt.Println(e.Field(i).Type().Kind())
        if !is_empty {
            break
        }
    }
default:
    checking_type = "default"
    // is_empty = IsEmptyStruct(e)
}
if is_show_checking {
    fmt.Println("Checking type :", checking_type, e.Type().Kind())
}
return is_empty
}

but this is not a good idea i think. the code will lose some type

ok i find a good way:

reflect.Zero(e.Type()) == e

and dont know whether this way will make some mistake when it is zero value in struct.
is there some way to check isset() like php? not empty() check in php

You might want to look at how encoding/json handles it:

thank you for your reply.
i see the function isEmptyValue, just like IsEmptyValue i write.
isEmptyValue is better.
i think there is no way to find out whether one variable is set or not.
because go will set one variable to zero value when defined automaticly.
len(array) == 0 or slice == nil this is easy to check.
a := 0
b := ""
this could not be checked.

For most cases the zero value is good enough.

If the zero value is not enough for what you need, then you need to explicitly keep track of when fields are set.

At that point I would really reconsider what I actually needed. For example, what harm is caused when a zero valued field is included or skipped? If it is just processing time or storage space, the cost of building a solution may be more than the resource use itself.

3 Likes

thank you for your patience.
i need to generate a query string with that struct.
the query string only contains the not null field in the struct value.
in the struct i given. the zero value checking is enough. :grinning:

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.