Go语言中反射(reflect)

作者: ropon 分类: Go 发布时间: 2019-12-19 16:58
package main

import (
	"fmt"
	"reflect"
)

//go语言中变量分为两部分
//	类型信息:预先定义好元信息
//	值信息:程序运行过程中可动态变化

//reflect包
//reflect.TypeOf 获取任意值的类型对象(reflect.Type)

//获取类型信息
func reflectType(x interface{}) {
	t := reflect.TypeOf(x)
	fmt.Printf("Type: %v, Kind: %v\n", t.Name(), t.Kind())
}

type cat struct {
	name string
}

type dog struct {
	name string
}

//Kind 获取种类 指底层类型
//go语言反射中 数组、切片、map、指针类型的变量 .Name() 返回是空

//reflect.ValueOf 返回的是reflect.Value,其中包含原始值信息
//reflect.Value 与 原始值 可相互转换

func reflectValue(x interface{}) {
	v := reflect.ValueOf(x)
	k := v.Kind()
	switch k {
	case reflect.Int64:
		fmt.Printf("Type: Int64, Value: %v\n", int64(v.Int()))
	}
}

//Elem() 获取指针对应的值
func reflectSetValue(x interface{}) {
	//t := reflect.TypeOf(x)
	//fmt.Println(t, t.Name(), t.Kind())
	v := reflect.ValueOf(x)
	//fmt.Println(v, v.Kind())
	v.Elem().SetInt(2)
}

//isNil、isValid

//func (v Value) IsNil() bool 检查v持有值是否为nil v持有类型必须是函数、接口、map、指针、切片之一
//func (v Value) IsValid() bool 检查v是否持有值 如果v是Value的零值返回假 此时v只有调用String、Kind方法
//IsNil常用于判断指针是否为空
//IsValid 常用于判断返回值是否有效

//结构体反射
//t := reflect.TypeOf(b)
//如果t的类型是结构体,还有以下方法
//t.Field(1) StructField 返回索引对应结构体字段的信息
//t.NumField() int 返回结构体字段数量
//t.FieldByName(name string) (StructField, bool) 根据指定字符串返回对应结构体字段的信息
//t.FieldByIndex(index []int) StructField 根据[]int提供的每个结构体字段索引返回对应结构体字段的信息
//t.FieldByNameFunc(match func(string) bool) (StructField, bool)
//t.NumMethod() int 返回方法数量
//t.Method(int) Method 返回第几个方法
//t.MethodByName(string) (Method, bool) 根据指定字符串返回具体方法

// StructField 类型  描述结构体中一个字典信息
//type StructField struct {
//	Name string // 字段名
//	PkgPath string
//	Type Type // 字段类型
//	Tag StructTag // 字典标签
//	Offset uintptr
//	Index []int
//	Anonymous bool //是否匿名字段
//}





type student struct {
	Name  string `json:name`
	Score int    `json:score`
}

//其他包要能调用,首字母必须大写
func (s student) Study() string {
	msg := "学习方法"
	return msg
}

func (s student) Sleep() string {
	msg := "睡觉方法"
	return msg
}

func (s student) TestFn(a string) string {
	msg := fmt.Sprintf("%s 测试函数返回值", a)
	return msg
}

func main() {
	//var a int64 = 200
	//reflectType(a)
	//var b float32 = 3.1415
	//reflectType(b)
	//c := dog{name: "wangcai"}
	//d := cat{name: "huahua"}
	//reflectType(c)
	//reflectType(d)
	//reflectType([3]int{})
	//reflectType([]int{})
	//reflectType(map[string]int{})
	//reflectType(&a)

	//var a int64 = 300
	//reflectValue(a)
	////将整型20转换为reflect.Value类型
	//b := reflect.ValueOf(20)
	//fmt.Printf("Type b: %T\n", b)

	//a := 100
	//reflectSetValue(&a)
	//fmt.Println(a)

	//var a *int
	//println(reflect.ValueOf(a).IsNil())
	//println(reflect.ValueOf(a).IsValid())

	//b := struct {name string; age int}{name:"Ropon", age: 18}
	//t := reflect.TypeOf(b)
	//fmt.Println(t.Field(1))
	//fmt.Println(t.NumField())
	//fmt.Println(t.FieldByName("age2"))

	//println(reflect.ValueOf(b).IsValid())

	//c := map[string]int{"Ropon": 2}
	//println(reflect.ValueOf(c).MapIndex(reflect.ValueOf("Ropon")).IsValid())

	stu1 := student{
		Name:  "Ropon",
		Score: 99,
	}
	//t := reflect.TypeOf(stu1)
	//fmt.Println(t.Name(), t.Kind())
	//for i := 0;i < t.NumField(); i ++ {
	//	filed := t.Field(i)
	//	fmt.Println(filed.Name, filed.Index, filed.Type, filed.Tag.Get("json"))
	//}
	//scoreField, ok := t.FieldByName("Score")
	//if ok {
	//	fmt.Println(scoreField.Name, scoreField.Index, scoreField.Type, scoreField.Tag.Get("json"))
	//}

	//fmt.Println(t.NumMethod())
	v := reflect.ValueOf(stu1)
	//for i := 0; i < t.NumMethod(); i++ {
	//	//fmt.Println(v.Method(i).Type(), t.Method(i).Name)
	//	//通过反射调用方法传递参数必须是 []reflect.Value类型
	//	fmt.Println(v.Method(i).Call([]reflect.Value{})[0])
	//}
	//有参数
	res := v.MethodByName("TestFn").Call([]reflect.Value{
		reflect.ValueOf("传入变量"),
	})
	fmt.Println(res[0])
}

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!