1 简介

反射是指在程序运行期对程序本身进行访问和修改的能力
变量包含类型信息和值信息

  • 类型信息:是静态的元信息,是预先定义好的
  • 值信息:是程序运行过程中动态改变的

reflect包封装了反射相关的方法

  • 获取类型信息:reflect.TypeOf,是静态的
  • 获取值信息:reflect.ValueOf,是动态的

    2 TypeOf, ValueOf

    ```go package main

import ( “fmt” “reflect” )

// 定义结构体 type User struct { Id int Name string Age int }

// 绑方法 func (u User) Hello() { fmt.Println(“Hello”) }

// 传入interface{} func Poni(o interface{}) { // 获取类型 t := reflect.TypeOf(o) fmt.Println(“类型:”, t) // main.User fmt.Println(“字符串类型:”, t.Name()) // User // 获取种类 k := t.Kind() fmt.Println(“种类:”, k) // struct // 获取值 v := reflect.ValueOf(o) fmt.Println(v) // {1 zs 20}

  1. // 获取结构体字段个数:t.NumField()
  2. for i := 0; i < t.NumField(); i++ {
  3. // 取每个字段
  4. f := t.Field(i)
  5. fmt.Printf("%s : %v", f.Name, f.Type) // Id : int
  6. // 获取字段的值信息
  7. // Interface():获取字段对应的值
  8. val := v.Field(i).Interface()
  9. fmt.Println("val :", val) // val : 1
  10. }
  11. // 获取结构体方法个数:t.NumMethod()
  12. for i := 0; i < t.NumMethod(); i++ {
  13. m := t.Method(i)
  14. fmt.Println(m.Name) // Hello
  15. fmt.Println(m.Type) // func(main.User)
  16. }

}

func main() { u := User{1, “zs”, 20} Poni(u) }

  1. <a name="pTbgQ"></a>
  2. # 3 DeepEqual
  3. ```go
  4. package main
  5. import (
  6. "fmt"
  7. "reflect"
  8. )
  9. func main() {
  10. s1 := []int{1, 2, 3}
  11. s2 := []int{1, 2, 3}
  12. s3 := []int{2, 3, 1}
  13. fmt.Println(reflect.DeepEqual(s1, s2), reflect.DeepEqual(s1, s3)) // true false
  14. }
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "reflect"
  6. )
  7. type Employee struct {
  8. Name string
  9. Age int
  10. }
  11. type Customer struct {
  12. Name string
  13. Age int
  14. }
  15. func fillBySettings(st interface{}, settings map[string]interface{}) error {
  16. if settings == nil {
  17. return errors.New("settings is nil")
  18. }
  19. if reflect.TypeOf(st).Kind() != reflect.Ptr {
  20. return errors.New("第一参数应是 指针")
  21. }
  22. if reflect.TypeOf(st).Elem().Kind() != reflect.Struct { // Elem()获取指针 指向的值
  23. return errors.New("第一参数应是 结构体指针")
  24. }
  25. var (
  26. field reflect.StructField
  27. ok bool
  28. )
  29. for k, v := range settings {
  30. if field, ok = (reflect.ValueOf(st)).Elem().Type().FieldByName(k); !ok {
  31. continue
  32. }
  33. if field.Type == reflect.TypeOf(v) {
  34. vstr := reflect.ValueOf(st)
  35. vstr = vstr.Elem()
  36. vstr.FieldByName(k).Set(reflect.ValueOf(v))
  37. }
  38. }
  39. return nil
  40. }
  41. func main() {
  42. settings := map[string]interface{}{"Name": "Mike", "Age": 40}
  43. e := &Employee{}
  44. _ = fillBySettings(e, settings)
  45. fmt.Println(e)
  46. c := new(Customer)
  47. _ = fillBySettings(c, settings)
  48. fmt.Println(c)
  49. fmt.Println(reflect.DeepEqual(e, c)) // false
  50. }