go反射深入学习

news2024/11/16 7:38:07

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.Value

var 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.coloradmin.cn/o/2241360.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI 写作(九)实战项目二:智能新闻报道(9/10)

一、项目概述 在当今信息爆炸的时代,新闻传播行业正面临着前所未有的挑战与机遇。随着科技的飞速发展,人们获取信息的渠道日益多样化,对新闻的时效性、准确性和个性化需求也不断提高。在这样的背景下,AI 写作在智能新闻报道中的重…

星际流浪的大模型

种子世界还在太空漫游,航线上捡到一个铁盒子,那是一块硬盘,古老的东西。 长老就安排歌者,你去研究,查查硬盘的来源坐标。 费好大劲,歌者把硬盘中的程序和数据激活,运行了起来。 很有意思&#x…

HarmonyOs DevEco Studio小技巧31--画布组件Canvas

那天我们用画布实现了文字颜色的渐变,实际上画布还有很多好玩的功能,接下来让我们一起试一下画布怎么玩 Canvas 提供画布组件,用于自定义绘制图形。 接口 Canvas Canvas(context?: CanvasRenderingContext2D | DrawingRenderingContext…

C语言.冒泡排序的练习

题目: 1.用C语言编程,用冒泡排序将一个元素个数为20,的一维数组,由大到小的降序。 分析:1.首先创建一个数组,元素个数为20. 2.其次是按降序排列。 3.最后用冒泡排序。 运行代码: #include&l…

RT-DETR融合GhostModel V3及相关改进思路

RT-DETR使用教程: RT-DETR使用教程 RT-DETR改进汇总贴:RT-DETR更新汇总贴 《GhostNetV3: Exploring the Training Strategies for Compact Models》 一、 模块介绍 论文链接:https://arxiv.org/pdf/2404.11202v1 代码链接:https:…

基于yolov8、yolov5的鸟类分类系统(含UI界面、训练好的模型、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下: 算法模型:     yolov8、yolov8 SE注意力机制 或 yolov5、yolov5 SE注意力机制 , 直接提供最少两个训练好的模型。模型十分重要,因为有些同学的电脑没有 GPU&#xff0…

如何保证MySQL与Redis缓存的数据一致性?

文章目录 一、引言二、场景来源三、高并发解决方案1. 先更新缓存,再更新数据库2. 先更新数据库,再更新缓存3. 先删除缓存,再更新数据库4. 先更新数据库,再删除缓存小结 四、拓展方案1. 分布式锁与分布式事务2. 消息队列3. 监听bin…

Chromium 中sqlite数据库操作演示c++

本文主要演示sqlite数据库 增删改查创建数据库以及数据库表的基本操作,仅供学习参考。 一、sqlite数据库操作类封装: sql\database.h sql\database.cc // Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-sty…

pycharm分支提交操作

一、Pycharm拉取Git远程仓库代码 1、点击VCS > Get from Version Control 2、输入git的url,选择自己的项目路径 3、点击Clone,就拉取成功了 默认签出分支为main 选择develop签出即可进行开发工作 二、创建分支(非必要可以不使用&#xf…

河道无人机雷达测流监测系统由哪几部分组成?

在现代水利管理中,河道无人机雷达监测系统正逐渐成为一种重要的工具,为河道的安全和管理提供了强大的技术支持。那么,这个先进的监测系统究竟由哪几部分组成呢? 河道无人机雷达监测系统工作原理 雷达传感器通过发射电磁波或激光束…

使用pycrawlers下载huggingface报错list index out of range问题解决

使用pycrawlers下载huggingface失败 错误:list index out of range 问题描述:当批量下载整个huggingface仓库的时候会报错,并且没有报错提示 分析:应该是哪个链接请求结果不存在数据 结果:当下载仓库存在文件夹下面只…

清华大学提出基于ESKF的松耦合里程计RINO:一种具有非迭代估计的精确、稳健的雷达惯性里程计

Abstract 精确的定位和建图对于实现自动驾驶车辆的自主导航至关重要。然而,当GNSS信号失效或在极端天气条件(例如雾、雨和雪)下,车体运动估计仍然面临重大挑战。近年来,扫描雷达因其较强的穿透能力成为一种有效的解决…

微信小程序之路由跳转传数据及接收

跳转并传id或者对象 1.home/index.wxml <!--点击goto方法 将spu_id传过去--> <view class"item" bind:tap"goto" data-id"{{item.spu_id}}"> 结果: 2.home/index.js goto(event){// 路由跳转页面,并把id传传过去//获取商品idlet i…

tensorflow案例6--基于VGG16的猫狗识别(准确率99.8%+),以及tqdm、train_on_batch的简介

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 本次还是学习API和如何搭建神经网络为主&#xff0c;这一次用VGG16去对猫狗分类&#xff0c;效果还是很好的&#xff0c;达到了99.8% 文章目录 1、tqdm…

海康大华宇视视频平台EasyCVR私有化视频平台服务器选购主要参数有哪些?

在构建现代服务器和视频监控系统时&#xff0c;选择合适的硬件配置和关键技术是确保系统性能和稳定性的基础。服务器选购涉及到多个关键参数&#xff0c;这些参数直接影响到服务器的处理能力、数据存储、网络通信等多个方面。 同时&#xff0c;随着视频监控技术的发展&#xf…

Redisson的可重入锁

初始状态&#xff1a; 表示系统或资源在没有线程持有锁的情况下的状态&#xff0c;任何线程都可以尝试获取锁。 线程 1 获得锁&#xff1a; 线程 1 首次获取了锁并进入受保护的代码区域。 线程 1 再次请求锁&#xff1a; 在持有锁的情况下&#xff0c;线程 1 再次请求锁&a…

Java-01 深入浅出 MyBatis - MyBatis 概念 ORM映射关系 常见ORM 详细发展历史

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…

C语言第13节:指针(3)

1. 回调函数 回调函数的基本思想是&#xff0c;将函数指针作为参数传递给另一个函数&#xff0c;并在需要时通过这个函数指针调用对应的函数。这种方式允许一个函数对执行的内容进行控制&#xff0c;而不需要知道具体的实现细节。 回调函数在以下场景中尤为有用&#xff1a; …

Tensorflow基本概念

简介&#xff1a;本文从Graph讲到Session&#xff0c;同时讲解了tf.constant创建tensor的用法和variable需要初始化的知识点&#xff0c;可以给你打好一个学习Tensorflow的基础。本文都是基于TensorFlow1.14.0的版本下运行。 本专栏将会系统的讲解TensorFlow在1.14.0版本下的各…

【包教包会】CocosCreator3.x框架——带翻页特效的场景切换

一、效果演示 二、如何获取 1、https://gitee.com/szrpf/TurnPage 2 2、解压&#xff0c;导入cocos creator&#xff08;版本3.8.2&#xff09;&#xff0c;可以直接运行Demo演示 三、算法思路 1、单场景 页面预制体 通过loadScene来切换页面&#xff0c;无法实现页面特效…