mardi 18 février 2020

How do I get at the contents of a private reflect.Value in go?

I'm trying to make a general purpose debug printer for complex data types because %v has a tendency to just print pointer values rather than what they point at. I've got it working with everything up until I have to deal with structs containing reflect.Value fields.

The following demo code runs without error: (https://play.golang.org/p/qvdRKc40R8k)

package main

import (
    "fmt"
    "reflect"
)

type MyStruct struct {
    i int
    R reflect.Value
}

func printContents(value interface{}) {
    // Omitted: check if value is actually a struct
    rv := reflect.ValueOf(value)
    for i := 0; i < rv.NumField(); i++ {
        fmt.Printf("%v: ", rv.Type().Field(i).Name)
        field := rv.Field(i)
        switch field.Kind() {
        case reflect.Int:
            fmt.Printf("%v", field.Int())
        case reflect.Struct:
            // Omitted: check if field is actually a reflect.Value to an int
            fmt.Printf("reflect.Value(%v)", field.Interface().(reflect.Value).Int())
        }
        fmt.Printf("\n")
    }
}

func main() {
    printContents(MyStruct{123, reflect.ValueOf(456)})
}

This prints:

i: 123
R: reflect.Value(456)

However, if I change MyStruct's R field name to r, it fails:

panic: reflect.Value.Interface: cannot return value obtained from unexported field or method

Of course, it's rightly failing because this would otherwise be a way to get an unexported field into proper goland, which is a no-no.

But this leaves me in a quandry: How can I gain access to whatever the unexported reflect.Value refers to without using Interface() so that I can walk its contents and print? I've looked through the reflect documentation and haven't found anything that looks helpful...





Aucun commentaire:

Enregistrer un commentaire