反射是用程序检查其所拥有的结构,尤其是类型的一种能力;这是元编程的一种形式。反射可以在运行时检查类型和变量,例如它的大小、方法和 动态
    的调用这些方法。这对于没有源代码的包尤其有用。这是一个强大的工具,除非真得有必要,否则应当避免使用或小心使用。
    变量的最基本信息就是类型和值:反射包的 Type 用来表示一个 Go 类型,反射包的 Value 为 Go 值提供了反射接口。
    两个简单的函数,reflect.TypeOfreflect.ValueOf,返回被检查对象的类型和值。例如,x 被定义为:var x float64 = 3.4,那么 reflect.TypeOf(x) 返回 float64reflect.ValueOf(x) 返回 <float64 Value>
    反射对象示例

    1. package main
    2. import (
    3. "fmt"
    4. "reflect"
    5. )
    6. type NotknownType struct {
    7. s1, s2, s3 string
    8. }
    9. func (n NotknownType) String() string {
    10. return n.s1 + " - " + n.s2 + " - " + n.s3
    11. }
    12. // variable to investigate:
    13. var secret interface{} = NotknownType{"Ada", "Go", "Oberon"}
    14. func main() {
    15. value := reflect.ValueOf(secret) // <main.NotknownType Value>
    16. typ := reflect.TypeOf(secret) // main.NotknownType
    17. // alternative:
    18. //typ := value.Type() // main.NotknownType
    19. fmt.Println(typ)
    20. knd := value.Kind() // struct
    21. fmt.Println(knd)
    22. // iterate through the fields of the struct:
    23. for i := 0; i < value.NumField(); i++ {
    24. fmt.Printf("Field %d: %v\n", i, value.Field(i))
    25. // error: panic: reflect.Value.SetString using value obtained using unexported field
    26. //value.Field(i).SetString("C#")
    27. }
    28. // call the first method, which is String():
    29. results := value.Method(0).Call(nil)
    30. fmt.Println(results) // [Ada - Go - Oberon]
    31. }