注意:反射获取字段给字段赋值时,该字段必须首字母大写,否则会引起恐慌报如下错误:
    panic: reflect: reflect.flag.mustBeAssignable using value obtained using unexported field

    1.变量结构
    type,value(pair)

    2.reflect包
    1.reflect类型

    1. const (
    2. Invalid Kind = iota //0~26
    3. Bool
    4. Int
    5. Int8
    6. Int16
    7. Int32
    8. Int64
    9. Uint
    10. Uint8
    11. Uint16
    12. Uint32
    13. Uint64
    14. Uintptr
    15. Float32
    16. Float64
    17. Complex64
    18. Complex128
    19. Array
    20. Chan
    21. Func
    22. Interface
    23. Map
    24. Ptr
    25. Slice
    26. String
    27. Struct
    28. UnsafePointer //26
    29. )

    2.获取kind

    1. package main
    2. import "reflect"
    3. type User struct {
    4. Name string
    5. Age int
    6. }
    7. func refTest(arg interface{}) {
    8. var argType reflect.Type = reflect.TypeOf(arg)
    9. var argValue reflect.Value = reflect.ValueOf(arg)
    10. print(argType.Kind())
    11. print(argValue.Kind())
    12. }
    13. func main() {
    14. refTest(User{"zhangsna", 11})
    15. //25 struct类型
    16. }

    3.获取属性

    1. package main
    2. import (
    3. "fmt"
    4. "reflect"
    5. )
    6. type User struct {
    7. //定义字段,并设置字段标签
    8. Name string `info:"名字" doc:"哈哈"`
    9. Age int `info:"年龄"`
    10. height float64 `info:"身高"`
    11. }
    12. func (user *User) GetName() string {
    13. return user.Name
    14. }
    15. //interface{}是万能数据类型
    16. func myFunc(arg interface{}) {
    17. //通过参数获取,参数的类型和值
    18. argType := reflect.TypeOf(arg)
    19. argValue := reflect.ValueOf(arg)
    20. //当arg是pir时,需要通过argType.Elem()获取属性,例如argType.Elem().NumField()
    21. for i := 0; i < argType.NumField(); i++ {
    22. //通过type获取内部字段类型和值
    23. field := argType.Field(i)
    24. value := argValue.Field(i)
    25. fmt.Println(field.Name, field.Type, value)
    26. //获取字段标签,Tag只存在类型里
    27. info := argType.Field(i).Tag.Get("info")
    28. doc := argType.Field(i).Tag.Get("doc")
    29. fmt.Println("标签info为:", info, "doc为", doc)
    30. }
    31. //通过type获取内部方法,只能获取非地址传值的方法
    32. for i := 0; i < argType.NumMethod(); i++ {
    33. method := argType.Method(i)
    34. fmt.Println(method.Name, method.Type)
    35. }
    36. }
    37. func main() {
    38. user := User{"张三", 24, 1.70}
    39. myFunc(user)
    40. }

    4.反射修改值

    1. package main
    2. import (
    3. "fmt"
    4. "reflect"
    5. )
    6. func refTest(arg interface{}) {
    7. argValue := reflect.ValueOf(arg)
    8. argValue.Elem().SetInt(10)
    9. }
    10. func main() {
    11. var a int = 11
    12. //必须传递指针
    13. refTest(&a)
    14. fmt.Println(a)
    15. }

    5.反射调用方法