Golang学习笔记-反射

反射让我们可以在运行时获取对象的类型信息,比如查看一个结构体有多少字段,查看函数的入参类型和返回值类型等。

Go提供了reflect.TypeOf()和reflect.ValueOf获取任意对象的reflect.Value和reflect.Type,其中reflect.Type是一个接口类型,该接口提供了很多方法让我们获取类型信息,而reflect.Value是一个结构体,它提供了很多方法让我们获取或者写入reflect.Value结构体中存储的数据。

获取类型信息

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	name string
	height int
}

func (person Person) AddHeight(height int)  string{
	person.height+=height
	return string(person.height)
}

func main(){
	//遍历结构体字段
	person:=Person{}
	valueType:=reflect.TypeOf(person)
	for i:=0;i<valueType.NumField();i++{
		field:=valueType.Field(i)
		fmt.Println(field.Name,field.Type)
	}
	//遍历结构体导出的方法
	for i:=0;i<valueType.NumMethod();i++{
		method:=valueType.Method(i)
		fmt.Println(method.Name)
	}
	//遍历函数参数和返回值
	valueType=reflect.TypeOf(Person{}.AddHeight)
	for i:=0;i<valueType.NumIn();i++{
		arg:=valueType.In(i)
		fmt.Println(arg)
	}
	for i:=0;i<valueType.NumOut();i++{
		result:=valueType.Out(i)
		fmt.Println(result)
	}

}

底层类型

使用Kind方法可以获取类型的底层类型,Go提供了以下底层类型:

const (
	Invalid Kind = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	Array
	Chan
	Func
	Interface
	Map
	Ptr
	Slice
	String
	Struct
	UnsafePointer
)

通过reflect.Value还原对象

使用Interface()方法可以将reflect.Value还原成接口类型,然后再强转一次就能还原成原本的类型。

func main(){
	value := reflect.ValueOf(1)
	fmt.Println(value.Interface().(int))
}

通过reflect.Value修改对象

如果想通过reflect.Value修改对象,那么reflect.ValueOf()需要传递对象的地址,然后通过Elem()方法找到这个指针指向的值才能修改,reflect.Value提供了CanSet()方法帮助我们判断是否可以修改该对象。

func main(){
	name:="xiongya"
	nameValue:=reflect.ValueOf(&name)
	nameValue.Elem().SetString("xy")
	fmt.Println(name)
}

动态调用方法

利用反射动态调用方法时参数和返回值都是reflect.Value切片。

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

type Person struct {
	name string
	height int
}

func (person Person) AddHeight(height int)  string{
	person.height+=height
	return strconv.Itoa(person.height)
}

func main(){
	person:=Person{"xiao hong",100}
	value:=reflect.ValueOf(person)
	method:=value.MethodByName("AddHeight")
	if method.IsValid(){
		args:=[]reflect.Value{reflect.ValueOf(10)}
		fmt.Println(method.Call(args))
	}
}
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页