Go语言基础之结构体反射

Go语言基础之结构体反射

前言

Hey,大家好呀,我是码农,星期八。

反射在结构体中的应用,才是最广泛的!毕竟在Go中,是用结构体代替对象的!

所以最多的,最麻烦的,也是反射结构体,也是最灵活的!

反射在结构体的应用

上次讲的,只是在普通变量中的应用,相对来说,使用的场景不是太多。

但是反射在结构体中的应用,基本会贯穿整个Go语言基础。

示例代码

结构体

type Student struct {
	Name   string   `json:"name" describe:"姓名"`
	Age    int      `json:"age" describe:"年龄"`
	Gender bool     `json:"gender" describe:"性别"`
	Hobby  []string `json:"hobby" describe:"爱好"`
}

main

func main() {
	//实例化结构体
	var s1 = Student{
		Name:   "张三",
		Age:    18,
		Gender: true,
		Hobby:  []string{"吃""喝""pia""玩"}}
	var t = reflect.TypeOf(s1)
	fmt.Println(t.Name())     //Student
	fmt.Println(t.Kind())     //struct
	fmt.Println(t.NumField()) //结果:4,表示多少个字段
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)//每个结构体对象
		/*
			{Name  string json:"name" describe:"姓名" 0 [0] false}
			{Age  int json:"age" describe:"年龄" 16 [1] false}
			{Gender  bool json:"gender" describe:"性别" 24 [2] false}
			{Hobby  []string json:"hobby" describe:"爱好" 32 [3] false}
		*/
		//fmt.Println(field)
		fmt.Println("------")
		fmt.Printf("field.Name:%v\n",field.Name)
		fmt.Printf("field.Index:%v\n",field.Index)
		fmt.Printf("field.Type:%v\n",field.Type)
		fmt.Printf("field.Tag:%v\n",field.Tag.Get("describe"))

	}
}

执行结果

在这里插入图片描述

单独反射指定字段信息

main代码

func main() {
	//实例化结构体
	var s1 = Student{
		Name:   "张三",
		Age:    18,
		Gender: true,
		Hobby:  []string{"吃""喝""pia""玩"}}
	var t = reflect.TypeOf(s1)
	genderField, ok := t.FieldByName("Gender")
	if ok {
		fmt.Println(genderField.Name)                //Gender
		fmt.Println(genderField.Index)               //[2]
		fmt.Println(genderField.Type)                //bool
		fmt.Println(genderField.Tag.Get("describe")) //性别
	}
}

ValueOf

上述的代码只能用的是TypeOf,只能返回类型等信息,相对来说不是太智能,ValueOf可以获取值,同样也能获取类型,相对来说比TypeOf好一点。

示例代码

main
func main() {
	//实例化结构体
	var s1 = Student{
		Name:   "张三",
		Age:    18,
		Gender: true,
		Hobby:  []string{"吃""喝""pia""玩"}}
	var v = reflect.ValueOf(s1)
	for i := 0; i < v.NumField(); i++ {
		field :=v.Field(i)
		fmt.Println("------")
		fmt.Printf("Kind:%v\n",field.Kind())
		fmt.Printf("值:%v\n",field.Interface())
	}
}

执行结果

在这里插入图片描述

反射方法

上述我们反射的都是值,有没有反射是否可以反射函数,并且调用函数呢??

结构体和绑定函数代码

type Student struct {
	Name   string   `json:"name" describe:"姓名"`
	Age    int      `json:"age" describe:"年龄"`
	Gender bool     `json:"gender" describe:"性别"`
	Hobby  []string `json:"hobby" describe:"爱好"`
}

//无参方法
func (this Student) Say() {
	fmt.Printf("我是%v,我的年龄是%v,我的性别是%v,我的爱好是%v\n", this.Name, this.Age, this.Gender, this.Hobby)
}
//有参数方法
func (this Student) Jump(distance int) {
	fmt.Printf("我是%v,我跳远跳了%v米\n", this.Name, distance)
}

main

func main() {
	//实例化结构体
	var s1 = Student{
		Name:   "张三",
		Age:    18,
		Gender: true,
		Hobby:  []string{"吃""喝""pia""玩"}}
	var t = reflect.TypeOf(s1)
	var v = reflect.ValueOf(s1)
	fmt.Println(v.NumMethod(),v.NumField())
	for i := 0; i < v.NumMethod(); i++ {
		method := v.Method(i)
		fmt.Println("--------")
		fmt.Println(method)//0x48c4e0 函数地址
		fmt.Println(method.Type())//func(int) 函数类型,形参和返回值
		fmt.Println(t.Method(i).Name)//Jump,函数名,注意,由t来调用的
	}
}

执行结果

在这里插入图片描述

反射调用函数

func main() {
	//实例化结构体
	var s1 = Student{
		Name:   "张三",
		Age:    18,
		Gender: true,
		Hobby:  []string{"吃""喝""pia""玩"}}
	var v = reflect.ValueOf(s1)

	//通过反射调用函数
	//调用Jump函数
	//反射调用函数必须传一个参数,不管有没有形参都要传
	//var args = []reflect.Value{}
	//v.MethodByName("Say").Call(args)

	//如果需要传参数
	//参数需要用reflect.ValueOf(1) 强转一下

	var args = []reflect.Value{reflect.ValueOf(2)}
	v.MethodByName("Jump").Call(args)
}

**注:**注意第14行和20行代码区别,如果要传参数,参考第20行代码。

执行结果

在这里插入图片描述

反射注意事项

在平常开发中,尽量慎用反射,原因如下。

  • 反射性能可能会比较低,毕竟是反正走的,一般比正向操作慢一两个级别。
  • 反射越多,代码越烂,TypeOfValueOf都有Kind,很多情况是TypeOfValueOf混用的,所以对于基础不好的,极不友好。
  • 在Go中,是没有try的,如果反射没有处理好异常,程序会直接崩溃,可能在意想不到的地方。

总结

上述我们主要讲述了Go反射结构体相关知识,包括有

  • 反射在结构体中的应用
  • 如何单独反射结构体字段信息
  • ValueOf其他操作
  • 如何放射结构体绑定的方法

到此为止反射就讲完了,一定要多尝试,多敲敲代码,反射的用法还有很多。

如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

我是码农星期八,如果觉得还不错,记得动手点赞一下哈。

感谢你的观看。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值