I expected in code to Work with struct Dish was EXPORTED as Dish. I expected the program to fail when a structure dish was unexported and not see the unexported field within it. (OK, I could see the unexported field being present in an EXPORTED STRUCTURE, but even that seems wrong).
But program still works as shown?? How can the reflection package see 'dish' if it is unexported?
--------------Program Follows---------- //Modified Example From blog: http://merbist.com/2011/06/27/golang-reflection-exampl/
package main
import (
"fmt"
"reflect"
)
func main() {
// iterate through the attributes of a Data Model instance
for name, mtype := range attributes(&dish{}) {
fmt.Printf("Name: %s, Type: %s\n", name, mtype)
}
}
// Data Model
type dish struct {
Id int
last string
Name string
Origin string
Query func()
}
// Example of how to use Go's reflection
// Print the attributes of a Data Model
func attributes(m interface{}) map[string]reflect.Type {
typ := reflect.TypeOf(m)
// if a pointer to a struct is passed, get the type of the dereferenced object
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
// create an attribute data structure as a map of types keyed by a string.
attrs := make(map[string]reflect.Type)
// Only structs are supported so return an empty result if the passed object
// isn't a struct
if typ.Kind() != reflect.Struct {
fmt.Printf("%v type can't have attributes inspected\n", typ.Kind())
return attrs
}
// loop through the struct's fields and set the map
for i := 0; i < typ.NumField(); i++ {
p := typ.Field(i)
fmt.Println("P = ", p)
if !p.Anonymous {
attrs[p.Name] = p.Type
}
}
return attrs
}
From: https://blog.golang.org/laws-of-reflection
the field names of T are upper case (exported) because only exported fields of a struct are settable."
This easily shows and proves the concept:
fmt.Printf("can set 'last'? %v; can set 'Id'? %v",
reflect.ValueOf(&dish{}).Elem().FieldByName("last").CanSet(),
reflect.ValueOf(&dish{}).Elem().FieldByName("Id").CanSet(),
)
This prints: can set 'last'? false; can set 'Id'? true
On the visibility of the type (struct) name ("dish" vs "Dish") that only affects the visibility when you directly use the type at compile time. For example:
import "whatever/something"
...
v := something.someStruct{} // will give compile error
...
// this can return an instance of someStruct, which can be inspected
// with reflect just like any other struct (and that works fine because
// we haven't directly put a literal "something.someStruct" in this code
v := something.SomeFunc()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With