go – 为什么反射与UNEXPORTED Struct和Unexported Fields一起使用?

我期望在代码中使用struct Dish被导出为Dish.

我预计当一个结构盘未被移出时,该程序会失败,并且看不到它内部未被移植的区域. (好吧,我可以看到未导出的字段出现在导出的结构中,但即使这看起来也不对).

但程序仍然如图所示?如果反映包装未被导出,它怎么能看到’菜’?

————–程序遵循———-
    //修改示例来自博客: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
}

最佳答案 来自:
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.”

这很容易显示和证明这个概念:

fmt.Printf("can set 'last'? %v; can set 'Id'? %v",
    reflect.ValueOf(&dish{}).Elem().FieldByName("last").CanSet(),
    reflect.ValueOf(&dish{}).Elem().FieldByName("Id").CanSet(),
)

这打印:可以设置’最后’?假;可以设置’Id’?真正

关于类型(struct)名称(“dish”vs“Dish”)的可见性,它只会在编译时直接使用类型时影响可见性.例如:

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()
点赞