Go反射学习笔记

文章目录

1、从类型对象中获取名称和种类

go 复制代码
const (
	Zero int = 0
)
func main() {
	type stu struct{}
	typeofCat := reflect.TypeOf(stu{})
	fmt.Println(typeofCat.Name(), typeofCat.Kind()) //显示反射类型对象名称和种类
	typeOfA := reflect.TypeOf(Zero)
	fmt.Println(typeOfA.Name(), typeOfA.Kind())
}

2、使用反射获取结构体的成员类型

方法 说明
Field(i int) StructField 根据索引规返回索引对应的结构字段的信息,当值不是结构体或索引越界会发生宕机
NumField() int 返回结构体成员字段数量,当类型不是结构体或索引越界时发生宕机
FieldByName(name string) (StructField bool) 根据给定字段返回字符串对应的结构体字段的信息,没有找到时bool返回false,当类型不是结构体或索引越界时发生宕机
FieldByIndex(index\[\]int) StructField 多层成员访问时,根据\[\]iny 提供的每个结构体的字段索引,返回字段的信息,没有找到返回零值。当类型不是结构体或索引越界时发生宕机
FieldByNameFunc(match func(string) bool)(StructField,bool) 根据匹配函数匹配需要的字段,当值不是结构体或索引越界时发生宕机

3、从反射值对象中获取值的方法

方法名 说明
Interface() interface{} 将值以interface{}类型返回,可以通过类型断言为指定类型
Int() int64 将值以int类型返回,所有有符号整数均可以此方式返回
Uint() uint64 将值以uint类型返回,所有无符号整数均可以此方式返回
Float() float64 将值以双精度类型返回,所有浮点数(float32,float64)均可以此方式返回
Bool() bool 将值以bool类型返回
Bytes() \[\]bytes 将值以字节数组\[\]bytes类型返回
String() string 将值以字符串类型返回
go 复制代码
func main() {
	var m int = 2021
	valueOfA := reflect.ValueOf(m)
	var getA int = valueOfA.Interface().(int)
	var getA2 int = int(valueOfA.Int())
	fmt.Println(getA, getA2)
}

4、使用反射访问结构体的成员字段的值

方法 说明
Field(i int) Value 根据索引对应的结构体成员字段的反射对象,当值不是结构体或索引越界时发生宕机
NumField() int 返回给结构体成员字段数量 ,当值不是结构体或索引越界时发生宕机
FieldByName(name string) Value 根据给定字符串返回字符串对应的结构体字段,没有找到时返回零值,当值不是结构体或索引越界时发生宕机
FieldByIndex(index \[\]int) Value 多层成员返回时,根据\[\]int提供的每个结构体的字段索引,返回字段的值,没有找到时返回零值,当值不是结构体或索引越界时发生宕机
FieldByNameFunc(match func(string) bool) value 根据匹配函数匹配需要的字段,找到时返回零值,当值不是结构体或索引越界时发生宕机
go 复制代码
type stu struct {
	a int
	b string
	float32
	bool
	next *stu
}

func main() {
	d := reflect.ValueOf(stu{
		next: &stu{},
	})
	fmt.Println("numField", d.NumField())
	floatField := d.Field(2)
	fmt.Println("floatField", floatField.Type())
	//根据名称查找字段
	fmt.Println("FieldsByName().Type", d.FieldByName("b").Type())
	fmt.Println("FieldByIndex()", d.FieldByIndex([]int{4, 0}).Type())
}

5、反射对象的空和有效性判断

| 方法 | 说明 |

| IsNil() bool | 返回值是否为nil,如果值类型不是通道(channel)、函数、接口、map、指针切片,类似于语言层的v==nil操作|

| IsValid() bool | 判断值是否有效。当值本身非法时,返回false,如reflect Value不包含任何值,值为nil等|

go 复制代码
func main() {
	var a *int
	fmt.Println("var a *int:", reflect.ValueOf(a).IsNil())
	fmt.Println("nil:", reflect.ValueOf(nil).IsValid())
	fmt.Println("*int nil:", reflect.ValueOf((*int)(nil)).Elem().IsValid())
	s := struct{}{}
	fmt.Println("struct:", reflect.ValueOf(s).FieldByName("").IsValid())
	fmt.Println("并不存在的结构体方法:", reflect.ValueOf(s).MethodByName("").IsValid())
	m := map[int]int{}
	fmt.Println("不存在的键:", reflect.ValueOf(m).MapIndex(reflect.ValueOf(3)).IsValid())

}

6、判定及获取元素的相关方法

方法名 说明
Elem() Value 取值指向的元素值,类似于语言层* 操作,当值类型不是指针或接口时发生宕机,空指针时返回nil的Value
Addr() Value 对寻址的值返回其地址,类似于语言层&操作,当值不可寻址时发生宕机
CanAddr() bool 表示值是否可寻址
CanSet() bool 返回值能否被修改,要求值可寻址且是导出的字段

7、值修改的相关方法

Set(x Value) 将值设置为传入反转值对象的值
SetUint(x uint64) 使用uint64设置值,当值的类型不是uint,uint8,uint16,uint32,uint64会发生宕机
SetInt(x int64) 比上面少了u
SetFloat(x float64) 使用float54设置值,当值的类型不是float32,float64发生宕机
SetBool(x bool) 使用bool设置值,当值的类型不是bool时发生宕机
SetBytes(x \[\]byte) 设置字节数组\[\] bytes值,当值的类型不是\[\]byte 会发生宕机
SetString(x string) 设置字符串值.当值的类型不是string时会发生宕机
  • 可被寻址
  • 可被导出
go 复制代码
func main() {
	a := 1024
	valueOfA := reflect.ValueOf(&a)
	valeOfEl := valueOfA.Elem()
	valeOfEl.SetInt(100)
	fmt.Println(a)

}
go 复制代码
func main() {
	type Dog struct {
		LegCount int
	}
	valueOfDog := reflect.ValueOf(&Dog{})
	valueOfDog = valueOfDog.Elem()
	vLegCount := valueOfDog.FieldByName("LegCount")
	vLegCount.SetInt(3)
	fmt.Println(vLegCount.Int())
}

8、通过类型创建类型

创建了新的类型

go 复制代码
func main() {
	var a int
	typeOfA := reflect.TypeOf(a)
	aIns := reflect.New(typeOfA)
	fmt.Println(aIns.Type(), aIns.Kind())
}

9、使用反射调用函数

go 复制代码
func add(a, b int) int {
	return a + b
}
func main() {
	funcValue := reflect.ValueOf(add)
	paramList := []reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20)}
	retList := funcValue.Call(paramList)
	fmt.Println(retList[0].Int())
}

10、常用反射API

从实例到Value

go 复制代码
func ValueOf(i interface{}) Value

从实例到Type

go 复制代码
func TypeOf (i interface{}) Type

从Type到Value

go 复制代码
func NewAt (type Type,p unsafe.Pointer) Value

从Value到Type

go 复制代码
func (v Value) Type() Type

从Value到实例

go 复制代码
func (v Value) Interface() (i interface{})
func (v Value)  Bool() bool
func (v Value) Float() float64
func (v Value) Int() int64
func (v Value) Uint() uint64

从Value的指针到值

go 复制代码
func (v Value) Elem() Value
func Indirect(v Value) Value

Type指针和值相互转换

go 复制代码
t.Elem() Type //指针类型Type到值类型Type
func PtrTo(t Type) Type

Value值的可修改性

go 复制代码
func (v Value) CanSet() bool
func (v Value) Set(x Value) 
相关推荐
敬往事一杯酒哈3 小时前
海康 AGV 导航读码器学习
学习
qq_284274055 小时前
机械原理笔记:平面机构自由度计算(复合铰链、局部自由度、虚约束)与四杆机构入门(含考点)
笔记·学习·平面·自动化·制造
徐小黑ACG6 小时前
Golang 基础05 结构体struct
开发语言·算法·golang
qq_284274056 小时前
数控铣床与加工中心笔记:铣刀与刀柄系统、G54试切对刀、镜像加工指令、孔加工工艺(钻扩铰镗)与固定循环G73/G83/G81/G76/G87/G84
笔记·学习·自动化·制造
Titan20247 小时前
MySQL访问个人学习笔记
笔记·学习·mysql
北冥you鱼8 小时前
Go 语言空接口(interface{})使用场景与最佳实践
开发语言·windows·golang
小雪崩8 小时前
嵌入式学习 day64:字符设备驱动
学习
深圳老胡8 小时前
STM32CubeMX 生成 CMake 工程,用 VSCode 编译与调试的完整流程
笔记·stm32·单片机·代码规范
个 人 练 习 生8 小时前
C++ string 类模拟实现:从底层理解字符串(上)
开发语言·c++·经验分享·学习·程序人生
坤坤子吖9 小时前
C++智能指针:RAII、shared_ptr与内存泄漏
开发语言·c++·笔记·学习