新闻动态

Go语言基础反射示例详解

发布日期:2022-02-01 00:03 | 文章来源:gibhub

概述

在程序运行期对程序动态的进行访问和修改

reflect godoc: https://golang.org/pkg/reflect/

reflect包有两个数据类型:

Type:数据类型 【reflect.TypeOf():是获取Type的方法】

Value:值的类型【reflect.ValueOf():是获取Value的方法】

语法

一、基本操作

获取变量类型

func TypeOf(i interface{}) Type//Type是interface{}的别名

例子

reflect.TypeOf(10)  //int
reflect.TypeOf(struct{ age int }{10})  //struct { age int }

获取变量的种类

reflect.TypeOf(struct{ age int }{10}).Kind()  //reflect.Struct
reflect.ValueOf("hello word").Kind()  //reflect.String

获取变量值

func ValueOf(i interface{}) Value//value是struct {}别名

例子

reflect.ValueOf("hello word")  //hello word
reflect.ValueOf(struct{ age int }{10})//{10}

二、修改目标对象

修改普通类型

str := "hello word"
reflect.ValueOf(&str).Elem().SetString("张三")

修改结构体

//第一步:ValueOf():传入一个变量的地址,返回是变量的地址  Elem():返回的是变量的原始值
elem:=reflect.ValueOf(&变量名).Elem()
//第二步 FieldByName():传入结构体字段名称SetString():传入你要修改的变量值
elem.FieldByName("Name").SetString("李四")
//定义一个User结构体
type User struct {
	Name string
	Age  int
}
user := User{Name: "张三", Age: 10}
//Elem() 获取user原始的值
elem := reflect.ValueOf(&user).Elem()
//FieldByName() 通过Name返回具有给定名称的结构字段 通过SetString 修改原始的值
elem.FieldByName("Name").SetString("李四")
elem.FieldByName("Age").SetInt(18)

三、动态调用方法

无参方法

//MethodByName():传方法名,方法名必须大小  Call():方法的形参
reflect.ValueOf(变量名).MethodByName(方法名).Call([]reflect.Value{})
reflect.ValueOf(变量名).MethodByName(方法名).Call(make([]reflect.Value, 0))
type User struct {
	Name string `json:"name" name:"张三"`
	Age  int
}
func (_ User) Say() {
	fmt.Println("user 说话")
}
user := User{Name: "张三", Age: 10}
reflect.ValueOf(&user).MethodByName("Say").Call([]reflect.Value{})
  reflect.ValueOf(user).MethodByName("Say").Call(make([]reflect.Value, 0))

有参方法

reflect.ValueOf(变量名).MethodByName(方法名).Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})
type User struct {
  Name string `json:"name" name:"张三"`
  Age  int
}
func (_ User) Say() {
  fmt.Println("user 说话")
}
user := User{Name: "张三", Age: 10}
reflect.ValueOf(user).MethodByName("SayContent").Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})

总结

反射调用struct的方法必须是公有的

反射调用无参方法时必修传 nil 或者 []reflect.Value{}

示例

package main
import (
	"fmt"
	"reflect"
)
func main() {
	//1. 获取变量类型
	fmt.Println("获取变量类型")
	fmt.Println(reflect.TypeOf(10))  //int
	fmt.Println(reflect.TypeOf(10.0))//float64
	fmt.Println(reflect.TypeOf(struct{ age int }{10})) //struct { age int }
	fmt.Println(reflect.TypeOf(map[string]string{"a": "a"})) //map[string]string
	fmt.Println("")
	//2. 获取变量值
	fmt.Println("获取变量值")
	fmt.Println(reflect.ValueOf("hello word")) //hello word
	fmt.Println(reflect.ValueOf(struct{ age int }{10})) //{10}
	fmt.Println(reflect.TypeOf(struct{ age int }{10}).Kind()) //struct
	//类型判断
	if t := reflect.TypeOf(struct{ age int }{10}).Kind(); t == reflect.Struct {
		fmt.Println("是结构体")
	} else {
		fmt.Println("不是结构体")
	}
	//修改目标对象
	str := "hello word"
	//普通变量修改
	reflect.ValueOf(&str).Elem().SetString("张三")
	fmt.Println(str)
	//结构体变量修改
	user := User{Name: "张三", Age: 10}
	//Elem() 获取user原始的值
	elem := reflect.ValueOf(&user).Elem()
	//FieldByName() 通过Name返回具有给定名称的结构字段 通过SetString 修改原始的值
	elem.FieldByName("Name").SetString("李四")
	elem.FieldByName("Age").SetInt(18)
	fmt.Println(user)
	//获取结构体的标签的值
	fmt.Println(reflect.TypeOf(&user).Elem().Field(0).Tag.Get("name"))
	//调用无参方法
	reflect.ValueOf(&user).MethodByName("Say").Call([]reflect.Value{})
	reflect.ValueOf(user).MethodByName("Say").Call(make([]reflect.Value, 0))
	//调用有参方法
	reflect.ValueOf(user).MethodByName("SayContent").Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})
	//调用本地的方法
	reflect.ValueOf(Hello).Call([]reflect.Value{})
	reflect.ValueOf(Hello).Call(nil)
	fmt.Printf("%#v\n", reflect.TypeOf(user).Field(0))
}
func Hello() {
	fmt.Println("hello")
}
type Person struct {
	Name string
}
type User struct {
	Person  // //反射会将匿名字段作为一个独立字段来处理
	Namestring `json:"name" name:"张三"`
	Age int
}
func (_ User) Say() {
	fmt.Println("user 说话")
}
func (_ User) SayContent(content string, a int) {
	fmt.Println("user", content, a)
}

以上就是Go语言基础反射示例详解的详细内容,更多关于Go语言反射的资料请关注本站其它相关文章!

美国服务器租用

版权声明:本站文章来源标注为YINGSOO的内容版权均为本站所有,欢迎引用、转载,请保持原文完整并注明来源及原文链接。禁止复制或仿造本网站,禁止在非www.yingsoo.com所属的服务器上建立镜像,否则将依法追究法律责任。本站部分内容来源于网友推荐、互联网收集整理而来,仅供学习参考,不代表本站立场,如有内容涉嫌侵权,请联系alex-e#qq.com处理。

相关文章

实时开通

自选配置、实时开通

免备案

全球线路精选!

全天候客户服务

7x24全年不间断在线

专属顾问服务

1对1客户咨询顾问

在线
客服

在线客服:7*24小时在线

客服
热线

400-630-3752
7*24小时客服服务热线

关注
微信

关注官方微信
顶部