反射

反射

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

Import("reflect")

两个函数

reflect.TypeOf,获取变量的类型,返回reflect.Type类型
reflect.ValueOf,获取变量的类型,返回reflect.Value类型
reflect.Value.Kind,获取变量的类别,返回一个常量
reflect.Value.Interface(),转换成interface{}类型

reflect.TypeOf

获取变量的类型

import (
	"fmt"
	"reflect"
)

func test(i interface{}) {
	t := reflect.TypeOf(i)
	fmt.Println(t)
}

func main() {
	var i int
	test(i)
}

reflect.ValueOf

将其他类型转换成reflect包的reflect.Value类型,就可以使用很多方法了

func test(i interface{}) {
	t := reflect.TypeOf(i)
	fmt.Println(t)
	of := reflect.ValueOf(i)
	k := of.Kind()
	fmt.Println(k)
	i2 := of.Interface()
	i3 := i2.(int)
	fmt.Println(i3)
}

通过反射来改变变量的值

  • reflect.Value.SetXX相关方法

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

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

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

// 使用Elem()相当于指针前面带了一个*
func test(i interface{}) {
	val := reflect.ValueOf(i)
	val.Elem().SetInt(100)
	fmt.Println(val.Elem())
}

func main() {
	var i int
	test(&i)   // 这里传指针,否则值类型传的是副本,修改值会报错
}

获取结构体字段以及方法的个数

type Student struct {
	Name  string
	Age   int
	Score float64
}

func main() {
	var stu = Student{
		Name:  "Eric",
		Age:   14,
		Score: 45.6,
	}
	test2(stu)
}

func test2(b interface{}) {
    val := reflect.ValueOf(b)
    kd := val.Kind()
    if kd != reflect.Struct {
	fmt.Printf("you kind is %T", kd)
	return
    }
    field := val.NumField()
    fmt.Println(field)
    
    method := val.NumMethod()
    fmt.Println(method)
}

用反射操作结构体的方法以及字段

reflect.Value.Method(n).Call(val []Value) 来调用结构体中的方法,n是第几个方法

reflect.Value.Field(n),n表示第几个字段

type Student struct {
	Name string
	Age int
	Score float64
}

func (s Student) Print() {
	fmt.Println("---- START ----")
	fmt.Println(s)
	fmt.Println("---- END ----")
}

func main() {
    var stu = Student{
	Name: "Eric",
	Age: 15,
	Score: 4.5,
    }
    var val []reflect.Value
    reflect.ValueOf(stu).Method(0).Call(val)
    // 获取字段
    fmt.Println(reflect.ValueOf(stu).Field(0))
    // 修改值,需要传入结构体指针,因为结构体是值类型,然后使用Elem()获取指针指向的值
    reflect.ValueOf(&stu).Elem().Field(0).SetString("Jin")
    fmt.Println(reflect.ValueOf(stu).Field(0))
}

获取结构体的tag

在json格式化的时候,我们可以给结构体定义一个别名用于序列化

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

func main() {
	var stu = Student{
		Name: "Eric",
		Age: 10,
		Score: 14.5,
	}
	bytes, _ := json.Marshal(stu)
	fmt.Println(string(bytes))
}

那么json包里面是如何获取这个tag的呢?

通过反射就可以获取

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

func main() {
	var stu = Student{
		Name:  "Eric",
		Age:   10,
		Score: 14.5,
	}
    // 通过反射获取Tag
	get := reflect.TypeOf(stu).Field(0).Tag.Get("json")
	fmt.Println(get)
}

 

posted @ 2019-05-24 16:35  Jin同学  阅读(139)  评论(0)    收藏  举报