golang中reflect的使用 @ 胡巴 | 星期一,二月 14 日,2022 年 | 2 分钟阅读 | 更新于 星期一,二月 14 日,2022 年

本篇文章记录golang中reflect的使用

package main

import (
	"fmt"
	"reflect"
)

type Animal interface {
	Run()
}

type Swimming struct{}
func(s *Swimming) swim() {
	fmt.Println("can swim!")
}

type Dog struct {
	Name    string
	Species string
	*Swimming
	age int
}

func (d *Dog) Bark() {
	fmt.Println("Wang Wang Wang ~~~")
}

func (d *Dog) Run() {
	fmt.Println(d.Name, " is running!")
}

// reflect.ValueOf 可以获取一个变量的类型
// 类型Type包含type和kind
// type例如main.Dog
// kind例如struct(golang中的那些数据类型)

// Type里有个rtype struct,rtype实现了Type接口中的
// 不同方法, 不同方法内部又根据实际Kind做了判断,
// 即不是所有方法都适用于任何Kind
// 例如 NumField方法,这个方法只有Kind == struct时才可以适用

// xxxType struct又都组合了rtype,因此也都实现了Type接口的方法
func main() {
	dog := Dog{
		Name:    "七宝",
		Species: "土狗",
	}
	typeOfDog := reflect.TypeOf(dog)
	fmt.Printf("typeOfDog is %s kindOfDog is %s\n", typeOfDog, typeOfDog.Kind())

	dogPtr := &dog
	typeOfDogPtr := reflect.TypeOf(dogPtr)
	fmt.Printf("typeOfDogPtr is %s kindOfDogPtr is %s\n", typeOfDogPtr, typeOfDogPtr.Kind())
	fmt.Println()

	// 这里主要使用NumField()方法获取struct中的字段数量
	// 然后通过Field(i)来获取具体的Field
	for i := 0; i < typeOfDog.NumField(); i++ {
		field := typeOfDog.Field(i)
		fmt.Println(field.Name, " ", field.Type, " ", field.Type.Kind())
	}
	fmt.Println()
	// 通过FieldByName可以获取指定名字的Field
	field, ok := typeOfDog.FieldByName("Name")
	if !ok {
		fmt.Println("no field:Name")
	} else {
		fmt.Println(field.Name, " ", field.Type, " ", field.Type.Kind())
	}
	fmt.Println()

	// 这里主要适用NumMethod()方法获取struct中的方法数量
	// 然后通过Method(i)获取具体的Method
	for i := 0; i < typeOfDogPtr.NumMethod(); i++ {
		method := typeOfDogPtr.Method(i)
		fmt.Println(method.Name, " ", method.Type, " ", method.Type.Kind())
	}
	fmt.Println()
	// 通过MethodByName可以判断struct是否拥有Run方法
	method, ok := typeOfDogPtr.MethodByName("Run")
	if !ok {
		fmt.Println("no method:Run")
	} else {
		fmt.Println(method.Name, " ", method.Type, " ", method.Type.Kind())
	}
	fmt.Println()

	// 这里验证了一下swim这个不可导出的方法是否可以通过reflect
	// 反射出来,结果是:不可以
	typeOfSwimming := reflect.TypeOf(Swimming{})
	for i := 0; i < typeOfSwimming.NumMethod(); i++ {
		method := typeOfSwimming.Method(i)
		fmt.Println(method.Name, " ", method.Type, " ", method.Type.Kind())
	}

	// ---------------------------valueOf----------------------------
	fmt.Println()
	name := "xiaoming"
	namePtr := reflect.ValueOf(&name).Elem()
	namePtrType := reflect.TypeOf(namePtr)
	fmt.Println(namePtrType.Name, " ", namePtrType, " ", namePtrType.Kind())
	namePtr.Set(reflect.ValueOf("xiaohong"))
	fmt.Println(name)
	fmt.Println(namePtr)
	fmt.Println()

	// 需要使用Elem()拿到dog的地址
	// 也就是需要拿到可寻址的地址后
	// 才能对它的属性进行修改
	valueOfDog := reflect.ValueOf(&dog)
	valueOfDogElem := valueOfDog.Elem()
	dogNameValue := valueOfDogElem.FieldByName("Name")
	dogNameValue.Set(reflect.ValueOf("大黄"))
	fmt.Println(dog)

	// 通过Call方法进行方法调用
	runMethod := valueOfDog.MethodByName("Run")
	returns := runMethod.Call([]reflect.Value{})
}

公众号: 无限递归

alt 搜索公众号:无限递归

Copyright © 2017 - 2018 boboidea.com All Rights Reserved 波波创意软件工作室 版权所有 【转载请注明出处】

avatar
基本信息
  • 姓名:bobo
  • 花名:胡巴
  • 性别:男
  • 血型:O型
  • 星座:白羊座

联系方式

  • 所在地:上海
  • QQ:279250819
  • 微信号:wanghuiwoshinideyou
  • 电子邮件:279250819@qq.com

博客地址

公众号

alt 无限递归

待学习的东西

  • docker
  • k8s
  • flink
  • flutter
  • golang源码
  • redis底层
  • 消息中间价原理
  • zabbix
  • opentracing
  • grafana
工作经历
  • 2019.6 - 至今

    • 公司:萌推(上海突进网络科技有限公司)
    • 职位:中级PHP工程师 & 初级golang工程师
    • 荣誉:
      • 绩效A连续得主
      • 月度之星
      • 优秀个人奖
    • 所作所为:
      • 利用ES优化OMS、MMS管理系统商品列表查询
      • 利用消息队列、Redis、乐观锁优化商品审核流程
      • 利用Redis对商家端接口进行有效限流
      • 优化商品相关表索引,提升SQL查询速度
      • 商品中台构建,统一商品相关操作
      • 大表优化(数据分离、分表、大字段拆分)
      • 掌握所有商品核心流程
  • 2018.5 - 2019.5

    • 公司:DaDa英语(上海卓赞教育信息科技有限公司)
    • 职位:中级PHP开发工程师
    • 荣誉:无
    • 所作所为:
      • 利用ES优化教师CMS系统统计数据接口至500ms内
      • 工单系统开发及持续优化
      • 教师CMS系统的功能开发及持续优化
  • 2018.3 - 2018.5

    • 公司:波奇(上海)信息科技有限公司
    • 职位:初级PHP开发工程师
    • 荣誉:同下
    • 所做作为:如下
  • 2016.7 - 2018.3

    • 公司:光橙(上海)信息科技有限公司
    • 职位:初级PHP开发工程师
    • 荣誉:
      • 年度最佳进步奖
    • 所作所为:
      • 利用Redis提升商详接口最佳响应速度至50ms内
      • 利用Redis提升双11活动页可承受QPS至500以上
      • 利用Redis对接口进行简单限流
      • 与小伙伴合作提升搜索质量(ES初识)
      • 其他C端接口的开发及优化
      • B端商城老页面的维护及优化
SKILLS

编程语言

  • PHP
  • Golang
  • Shell
  • JAVA
  • JS
  • HTML\CSS

数据库

  • MySQL
  • Redis
  • 具有简单分表经验

消息中间件

  • RabbitMq
  • Kafka

文档撰写

  • Swagger
  • Markdown

技术框架

  • Laravel
  • gin

搜索引擎

  • ElasticSearch

抓包工具

  • Charles