Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

golang - reflection on embedded structs

Tags:

go

Given a struct like so:

type B struct {     X string     Y string }  type D struct {     B     Z string } 

I want to reflect on D and get to the fields X, Y, Z.

Intuitively, before attempting the solution, I was assuming I would be able to traverse the struct D and get all fields using reflection (X, Y, Z) and won't have to deal with B.

But as you can see, I only see the embedded struct B using reflection and not its fields.

http://play.golang.org/p/qZQD5GdTA8

Is there a way I can make B fully transparent when reflecting on D?

Why do I want this?

Imaging a common struct (B in the example here), that is used in multiple other structs by using embedding. Using reflection, the attempt is to copy D into another similar struct in a different package. The destination struct for copying will have all attributes flatly laid out (no embedding there). So there is a mismatch from the source to the destination (embedding vs no embedding) but all the attributes flatly laid out are the same. I don't want to create custom solutions for each struct.

like image 849
sat Avatar asked Jun 20 '14 18:06

sat


1 Answers

The 'transparency' you expected is just syntactic sugar and has nothing to do with the data representation. If you want to have a function that flattens your data structure, you would have to write it by yourself.

For example (On play):

func DeepFields(iface interface{}) []reflect.Value {     fields := make([]reflect.Value, 0)     ifv := reflect.ValueOf(iface)     ift := reflect.TypeOf(iface)      for i := 0; i < ift.NumField(); i++ {         v := ifv.Field(i)          switch v.Kind() {         case reflect.Struct:             fields = append(fields, DeepFields(v.Interface())...)         default:             fields = append(fields, v)         }     }      return fields } 
like image 92
nemo Avatar answered Oct 02 '22 23:10

nemo