go反射深入学习

news/2024/11/16 18:18:06/

Go 语言中的反射详解
反射是 Go 语言中的一个强大功能,可以在运行时动态获取和操作类型和值。了解反射有助于构建更灵活和通用的代码。本篇博客主要介绍 Go 语言反射的三大基本定律及其相关用法。

  1. 反射第一定律:反射可以将 interface 类型变量转换成反射对象
    基本用法
    通过 reflect.TypeOf() 和 reflect.ValueOf(),可以从 interface 类型变量中获取反射对象的类型和值。例如:

go
复制代码
package main

import (
“fmt”
“reflect”
)

func main() {
var x float64 = 3.4
t := reflect.TypeOf(x) // t 是 reflect.Type
fmt.Println(“type:”, t)

v := reflect.ValueOf(x) // v 是 reflect.Value
fmt.Println("value:", v)

}
输出:

go
复制代码
type: float64
value: 3.4
解释
reflect.TypeOf() 和 reflect.ValueOf() 都接受 interface{} 类型参数,表明 x 在调用时会被转换为 interface。通过 reflect.Value 和 reflect.Type,我们可以在运行时获取变量的具体信息。

  1. 反射第二定律:反射对象可以还原为 interface 对象
    反射与 interface 之间是可以相互转换的。以下代码展示如何从反射对象还原为具体的 interface 对象:

go
复制代码
package main

import (
“fmt”
“reflect”
)

func main() {
var x float64 = 3.4

v := reflect.ValueOf(x) // v 是 reflect.Valuevar y float64 = v.Interface().(float64)
fmt.Println("value:", y)

}
输出:

makefile
复制代码
value: 3.4
解释
我们将对象 x 转换成了反射对象 v,然后通过 v.Interface() 将 v 转回 interface{},最后用类型断言将其还原为 float64。这种方式展示了反射对象与具体类型对象之间的互操作能力。

  1. 反射第三定律:反射对象可修改,Value 值必须是可设置的
    为了说明反射如何修改值,我们先看一个失败的例子:

go
复制代码
package main

import (
“reflect”
)

func main() {
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // Error: will panic.
}
输出:

vbnet
复制代码
panic: reflect: reflect.Value.SetFloat using unaddressable value
解释
错误的原因是 v 是不可修改的。传递给 reflect.ValueOf() 的是 x 的值,而不是 x 的地址。由于 Go 语言的函数传参机制是值传递,反射修改 v 的值是无效的。

正确的修改方式
我们需要传递 x 的地址,并使用 Elem() 获取指针指向的值:

go
复制代码
package main

import (
“fmt”
“reflect”
)

func main() {
var x float64 = 3.4
v := reflect.ValueOf(&x) // 传递 x 的地址
v.Elem().SetFloat(7.1) // 修改指针指向的值
fmt.Println(“x :”, v.Elem().Interface())
}
输出:

yaml
复制代码
x : 7.1
解释
reflect.ValueOf(&x) 将 x 的地址传递给 reflect.Value,这使得我们能够通过反射修改 x 的值。v.Elem() 用于获取指针指向的实际值,从而允许修改。

总结
反射第一定律:反射可以将 interface 类型变量转换成反射对象,利用 reflect.TypeOf() 和 reflect.ValueOf() 获取类型和值。
反射第二定律:反射对象可以还原为 interface 对象,通过 Interface() 方法实现。
反射第三定律:要修改反射对象,其值必须是可设置的;通常需要使用指针来获取和修改值。
反射是 Go 语言中构建动态和灵活代码的关键工具,但需要注意性能开销和可能引入的复杂性。了解反射的基本定律和用法,可以更好地掌握和使用 Go 的强大特性。


http://www.ppmy.cn/news/1547509.html

相关文章

阿里云SSL证书每三个月过期续期方法 —— 使用httpsok工具轻松自动续期

阿里云作为全球领先的云计算服务提供商,提供了SSL证书服务,可以为网站启用HTTPS加密,确保数据传输的安全。然而,许多人在使用阿里云SSL证书时可能会遇到一个问题:阿里云免费SSL证书每三个月就会过期,需要及…

AR眼镜方案_AR智能眼镜阵列/衍射光波导显示方案

在当今AR智能眼镜的发展中,显示和光学组件成为了技术攻坚的主要领域。由于这些组件的高制造难度和成本,其光学显示模块在整个设备的成本中约占40%。 采用光波导技术的AR眼镜显示方案,核心结构通常由光机、波导和耦合器组成。光机内的微型显示…

Scala 的List

Scala列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同。首先,列表是不可变的,值一旦被定义了就不能改变,其次,列表具有递归的结构(也就是链表结构), 而数组不是。列表的元素类型T可…

协方差矩阵及其计算方法

协方差矩阵(Covariance Matrix)是一个描述多维数据特征之间相互关系的矩阵,广泛应用于统计学和机器学习中。它用于表示各个特征之间的协方差,是分析多维数据分布和特征依赖性的重要工具。 什么是协方差矩阵? 协方差矩…

快速利用c语言实现线性表(lineList)

线性表是数据结构中最基本和简单的一个,它是n的相同类型数据的有序序列,我们也可以用c语言中的数组来理解线性表。 一、线性表声明 我们定义一个线性表的结构体,内部有三个元素:其中elem是一个指针,指向线性表的头&am…

力扣 LeetCode 1047. 删除字符串中的所有相邻重复项(Day5:栈与队列)

解题思路&#xff1a; 方法一&#xff1a;栈 class Solution {public String removeDuplicates(String s) {Deque<Character> stack new ArrayDeque<>();for (char c : s.toCharArray()) {if (stack.isEmpty() || stack.peek() ! c) stack.push(c);else stack.p…

ubuntu下openssl签名证书制作流程及验证demo

1.创建根CA证书 生成 rootCA.key 以及 rootCA.crt. 用你的域名或者ip地址替换demo.mlopshub.com&#xff0c;比如192.168.10.11 openssl req -x509 \-sha256 -days 356 \-nodes \-newkey rsa:2048 \-subj "/CNdemo.mlopshub.com/CCN/LBeijing" \-keyout rootCA.key …

fpga 同步fifo

FIFO 基础知识 FIFO&#xff08;First In First Out&#xff0c;即先入先出&#xff09;&#xff0c;是一种数据缓存器&#xff0c;用来实现数据先入先出 的读写方式。在 FPGA 或者 ASIC 中使用到的 FIFO 一般指的是对数据的存储具有先入先出 特性的缓存器&#xff0c;常被用于…