GO开发[六]:golang反射,reflect

反射:可以在运行时动态获取变量的相关信息

​ Import (“reflect”)

reflect.TypeOf,获取变量的类型,返回reflect.Type类型

reflect.ValueOf,获取变量的值,返回reflect.Value类型

reflect.Value.Kind,获取变量的类别,返回一个常量

reflect.Value.Interface(),转换成interface{}类型

获取变量的值:

reflect.ValueOf(x).Float()

reflect.ValueOf(x).Int()

reflect.ValueOf(x).String()

reflect.ValueOf(x).Bool()

通过反射的来改变变量的值

reflect.Value.SetXX相关方法,比如:

reflect.Value.SetFloat(),设置浮点数

reflect.Value.SetInt(),设置整数

reflect.Value.SetString(),设置字符串

package main

import (
   "fmt"
   "reflect"
)

type Student struct {
   Name  string
   Age   int
   Score float32
}

func test(b interface{}) {
   //t是b的一个拷贝,修改t,b不会修改!
   t := reflect.TypeOf(b) //获取变量的类型,返回reflect.Type类型
   fmt.Println(t)
   v := reflect.ValueOf(b) //获取变量的值,返回reflect.Value类型
   fmt.Println(v)
   k := v.Kind() //获取变量的类别,返回一个常量
   fmt.Println(k)

   iv := v.Interface()
   stu, ok := iv.(Student)
   if ok {
      fmt.Printf("%v %T\n", stu, stu)
   }
}

func testInt(b interface{}) {
   val := reflect.ValueOf(b)
   fmt.Println(val.Elem())
   val.Elem().SetInt(100)
   //val.Elem()用来获取指针指向的变量,相当于:
   //var a *int;
   //*a = 100
   c := val.Elem().Int()
   fmt.Printf("get value  interface{} %d\n", c)
   fmt.Printf("string val:%d\n", val.Elem().Int())
}

func main() {
   var a Student = Student{
      Name:  "stu01",
      Age:   18,
      Score: 92,
   }
   test(a)

   var b int = 1
   b = 200
   testInt(&b)
   fmt.Println(b)
}

用反射操作结构体

reflect.Value.NumField()获取结构体中字段的个数

reflect.Value.Method(n).Call来调用结构体中的方法

package main

import (
    "fmt"
    "reflect"
)

type NotknownType struct {
    s1 string
    s2 string
    s3 string
}
func (n NotknownType) String() string {
    return n.s1 + "-" + n.s2 + "-" + n.s3
}

var secret interface{} = NotknownType{"greg", "learn", "go"}

func main() {
    value := reflect.ValueOf(secret) // <main.NotknownType Value>
    typ := reflect.TypeOf(secret)    // main.NotknownType
    fmt.Println(value,typ)

    knd := value.Kind() // struct
    fmt.Println(knd)

    for i := 0; i < value.NumField(); i++ {
        //value.Field(i).SetString("ningxin")
        fmt.Printf("Field %d: %v\n", i, value.Field(i))
    }

    results := value.Method(0).Call(nil)
    fmt.Printf("%T\n",results)
    fmt.Println(results)
}

反射回调函数和方法

package main

import (
   "fmt"
   "reflect"
)

type Student struct {
   Name  string
   Age   int
   Score float64
   Sex   string
}

func (s Student) Print() {
   fmt.Println("---start----")
   fmt.Println(s)
   fmt.Println("---end----")
}

func (s Student) Set(name string, age int, score float64, sex string) {
   s.Name = name
   s.Age = age
   s.Score = score
   s.Sex = sex
   fmt.Println(s)
}

func TestStruct(a interface{}) {
   val := reflect.ValueOf(a)
   kd := val.Kind()
   if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct {
      fmt.Println("expect struct")
      return
   }

   num := val.Elem().NumField()
   val.Elem().Field(0).SetString("greg")

   for i := 0; i < num; i++ {
      fmt.Printf("%d %v\n", i, val.Elem().Field(i).Kind())
   }

   fmt.Printf("struct has %d fields\n", num)
   numOfMethod := val.Elem().NumMethod()
   fmt.Printf("struct has %d methods\n", numOfMethod)

   val.Elem().Method(0).Call(nil)

   params := make([]reflect.Value,4)
   params[0]=reflect.ValueOf("hhhhhhhhh")
   params[1]=reflect.ValueOf(188888888)
   params[2]=reflect.ValueOf(59.99999)
   params[3]=reflect.ValueOf("male")
   //fmt.Println(params)
   val.Elem().Method(1).Call(params)
}

func main() {
   var a Student = Student{
      Name:  "ningxin",
      Age:   18,
      Score: 92.8,
   }
   fmt.Println(a)
   TestStruct(&a)
}

json序列化是通过反射实现的

package main

import (
   "encoding/json"
   "fmt"
   "reflect"
)

type Student struct {
   Name  string `json:"student_name"`
   Age   int
   Score float32
   Sex   string
}

func (s Student) Set(name string, age int, score float32, sex string) {
   s.Name = name
   s.Age = age
   s.Score = score
   s.Sex = sex
}

func Tagtest(a interface{}) {
   tye := reflect.TypeOf(a)
   fmt.Println("///////////",tye)
   fmt.Println(tye.Elem())
   fmt.Println(tye.Elem().Field(0))
   fmt.Println(tye.Elem().Field(0).Tag)
   tag := tye.Elem().Field(0).Tag.Get("json")
   fmt.Printf("tag=%s///////////\n", tag)
}

func main() {
   var a Student = Student{
      Name:  "stu01",
      Age:   18,
      Score: 92.8,
   }

   result, _ := json.Marshal(a)
   fmt.Println("json result:", string(result))
   Tagtest(&a)
   fmt.Println(a)
}