首页 > 其他分享 >14、go的反射

14、go的反射

时间:2022-11-25 16:15:23浏览次数:51  
标签:反射 14 fmt reflect Println func Student go reValue

基本数据类型反射

// 利用函数的参数定义为空接口
func testRefect(i interface{}) {
	// 调用TypeOf函数,返回reflect.Type类型的数据
	reType := reflect.TypeOf(i)
	fmt.Println(reType) // int
	// 调用ValueOf函数,返回reflect.Value类型数据
	reValue := reflect.ValueOf(i)
	fmt.Println(reValue) // 100
	// 虽然看着打印的是100这个数值,但它是value类型
	//num := 100 + reValue	// 这样编译就会直接报错了
	// 如果想要获取reValue的数值,用它的Int()方法
	num := 100 + reValue.Int()
	fmt.Println(num) // 200

	// reValue转成空接口
	a := reValue.Interface()
	// 类型断言
	i2 := a.(int)
	i3 := i2 + 30
	fmt.Println(i3) // 130
}
func main() {
	// 对基本数据类型进行反射
	var num int = 100
	testRefect(num)
}

image

反射对结构体反射

// 定义学生结构体
type Student struct {
	Name string
	Age  int
}

func testRefect2(i interface{}) {
	// 调用TypeOf函数,返回reflect.Type类型的数据
	reType := reflect.TypeOf(i)
	fmt.Println(reType) //main.Student
	// 调用ValueOf函数,返回reflect.Value类型数据
	reValue := reflect.ValueOf(i)
	fmt.Println(reValue) //{二狗 18}
	// reValue转成空接口
	a := reValue.Interface()
	student, flag := a.(Student)
	if flag { // 断言成功的话
		fmt.Printf("姓名:%v, 年龄:%v", student.Name, student.Age) //姓名:二狗, 年龄:18
	}
}
func main() {
	student := Student{
		Name: "二狗",
		Age:  18,
	}
	testRefect2(student)
}

反射获取变量类别

// 定义学生结构体
type Student struct {
	Name string
	Age  int
}

func testRefect3(i interface{}) {
	// 调用TypeOf函数,返回reflect.Type类型的数据
	reType := reflect.TypeOf(i)
	// 调用ValueOf函数,返回reflect.Value类型数据
	reValue := reflect.ValueOf(i)
	// 通过reType获取变量的类别
	kind := reType.Kind()
	fmt.Println(kind) // struct
	// 通过reValue获取,类别是否一样
	kind2 := reValue.Kind()
	fmt.Println(kind2) //struct

	// 获取变量的类型
	// reValue转成空接口
	a := reValue.Interface()
	student, flag := a.(Student)
	if flag { // 断言成功的话
		fmt.Printf("结构体类型:%T", student) //结构体类型:main.Student
	}

}
func main() {
	student := Student{
		Name: "二狗",
		Age:  18,
	}
	testRefect3(student)
}

反射修改变量的值

func testRefect4(i interface{}) {
	reValue := reflect.ValueOf(i)
	// 通过SetInt()改变值
	reValue.Elem().SetInt(40)
}
func main() {
	var num int = 100
	testRefect4(&num) // 传指针地址h
	fmt.Println(num)	// 40
}

反射操作结构体

// 定义学生结构体
type Student struct {
	Name string
	Age  int
}

func (s Student) CPrint() {
	fmt.Println("调用了Print()方法")
	fmt.Println("名字是:", s.Name)
}
func (s Student) AGetSum(n1, n2 int) int {
	fmt.Println("调用了AGetSum()方法")
	return n1 + n2
}
func (s Student) BSet(name string, age int) {
	s.Name = name
	s.Age = age
}

// 定义函数操作结构体进行反射
func TestStudentStruct(a interface{}) {
	// a转reflect.Value类型
	val := reflect.ValueOf(a)
	fmt.Println(val) // {二狗 18}

	// 通过reflect.Value类型操作结构体内部字段
	field := val.NumField()
	fmt.Println(field) // 2
	// 获取具体字段,field是字段数量
	for i := 0; i < field; i++ {
		fmt.Printf("第%d个字段的值是:%v \n", i, val.Field(i))
	}

	// 通过reflect.Value类型操作结构体方法
	method := val.NumMethod()
	fmt.Println(method) // 3

	//调用CPrint()方法
	// 方法顺序安装ASCII顺序排列的,注意方法名首字母大写
	val.Method(2).Call(nil)

	//调用AGetSum()方法
	// 定义value的切片
	var params []reflect.Value
	params = append(params, reflect.ValueOf(10))
	params = append(params, reflect.ValueOf(20))
	call := val.Method(0).Call(params)
	fmt.Println(call[0].Int())	// 30
}
func main() {
	student := Student{
		Name: "二狗",
		Age:  18,
	}
	TestStudentStruct(student)
}

打印:
image

反射修改变量值

// 定义学生结构体
type Student struct {
	Name string
	Age  int
}

// 定义函数操作结构体进行反射
func TestStudentStruct(a interface{}) {
	// a转reflect.Value类型
	val := reflect.ValueOf(a)
	fmt.Println(val) // {二狗 18}

	numField := val.Elem().NumField()
	fmt.Println(numField)

	// 修改字段的值
	val.Elem().Field(0).SetString("张三")
}
func main() {
	student := Student{
		Name: "二狗",
		Age:  18,
	}
	TestStudentStruct(&student)
	fmt.Println(student)
}

标签:反射,14,fmt,reflect,Println,func,Student,go,reValue
From: https://www.cnblogs.com/abiu/p/16417054.html

相关文章

  • 13、go的TCP网络编程
    创建客户端funcmain(){ //所需的网络编程全都在net包下 conn,err:=net.Dial("tcp","127.0.0.1:8888") fmt.Println("客户端启动") iferr!=nil{//连接失......
  • 12、go的协程和管道
    协程概念又称微线程,纤程,协程是一种用户态的轻量级线程作用:在执行A函数时候,可以随时中断,去执行B函数,然后中断继续执行A函数(可以自动切换),这一切换过程并不是函数调用(没有调......
  • 11、go的文件操作
    文件创建一个测试文件代码测试:funcmain(){ //打开文件 file,err:=os.Open("E:/test/Test.txt") iferr!=nil{//err不为空,说明报错 fmt.Println("文件......
  • 10、go的面向对象
    结构体结构体的定义//定义结构体,老师的结构体,各个属性统一放入结构体管理typeTeacherstruct{ //变量名大写开头外界可以访问 Namestring Ageint Scho......
  • 9、go的map
    map引入funcmain(){ //定义map varamap[int]string //只声明map内存是没有分配空间的,必须通过make函数进行初始化 a=make(map[int]string,10)//如果不指......
  • Memcache,Redis,MongoDB(数据缓存系统)方案对比与分析
    摘要:一、问题:      数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求。 二、解决方案:   1.通过高速服务器Cache......
  • MongoDB - 事务支持
    事务简介事务是数据库中处理的逻辑单元,每个事务中包括一个或多个数据库操作,既可以是读操作,也可以是写操作。ACID是一个“真正”事务所需要具备的一组属性集合,指的是原子......
  • centos 7 YUM 安装mongodb 3.4
    第一步查看是否存在Mongodb配置yum源切换到yum目录cd/etc/yum.repos.d/查看文件ls第二部不存在添加yum源创建文件touchmongodb-3.4.repo编辑该文件vimongodb-3.4.......
  • Go 语言系列20:defer 延迟调用
    含有​​defer​​​语句的函数,会在该函数将要返回之前,调用另一个函数。简单点说就是​​defer​​语句后面跟着的函数会延迟到当前函数执行完后再执行。下面是一个简单......
  • Go 语言系列23:接口
    在Go语言中,接口就是方法签名(MethodSignature)的集合。在面向对象的领域里,接口定义一个对象的行为,接口只指定了对象应该做什么,至于如何实现这个行为,则由对象本身去确定......