go反射实战

文章目录

  • demo1 数据类型判断
  • demo2 打印任意类型数据

demo1 数据类型判断

  1. 使用reflect.TypeOf()方法打印go中数据类型,可参考go官方API文档;
  2. 使用格式化参数%T也能打印数据类型。
package mainimport "fmt"
import "reflect"
import "io"
import "os"func main() {TypeTest()
}func TypeTest() {tInt := reflect.TypeOf(3)               // inttStr := reflect.TypeOf("文字")           // stringtBool := reflect.TypeOf(true)            // booltFloat := reflect.TypeOf(3.14)           // float64tSlice := reflect.TypeOf([]int{1, 2})    // []inttMap := reflect.TypeOf(map[int]string{}) // map[int]stringvar w io.Writer = os.Stdout              // *os.FiletW := reflect.TypeOf(w)fmt.Println(tInt, tStr, tBool, tFloat, tSlice, tMap, tW)fmt.Printf("%T %T %T %T %T %T %T", 3, "feng", true, 3.14, []int{1, 2}, map[int]string{}, os.Stdout)
}

输出

int string bool float64 []int map[int]string *os.File
int string bool float64 []int map[int]string *os.File

demo2 打印任意类型数据

开始写代码之前,简单了解一些reflect包中的结构体和方法。

1.结构体:reflect.Value(类型+数据指针)

type Value struct {typ *rtypeptr unsafe.Pointerflag
}
type flag uintptr

2.方法:reflect.ValueOf()
入参:接口interface{},也就是任意类型
出参:reflect.Value结构体

func ValueOf(i any) Value {if i == nil {return Value{}}escapes(i)return unpackEface(i)
}

3.方法:reflect.Value{}.Interface()
将Value的数据值转为interface{}类型

func (v Value) Interface() (i any) {return valueInterface(v, true)
}

4.类型:reflect.Kind
实际上Kind是一个uint类型的别名,使用Kind类型定义了go中各种数据类型,枚举如下
(iota变量是0,常量块定义中使用iota,后面的如果没有指定数值,一般就是自增)

type Kind uintconst (Invalid Kind = iotaBoolIntInt8Int16Int32Int64UintUint8Uint16Uint32Uint64UintptrFloat32Float64Complex64Complex128ArrayChanFuncInterfaceMapPointerSliceStringStructUnsafePointer
)
  1. 结构体:reflect.Type(数据类型)
type Type interface {// 对齐方式Align() int// 结构体字段的对齐方式FieldAlign() int// 从方法集合中返回索引为i的方法Method(int) Method// 通过方法名在方法集合中找方法,返回方法和是否找到的bool类型结果MethodByName(string) (Method, bool)// 返回方法数量NumMethod() int// 返回类型的名称,例如 int、string等Name() string//  返回包路径,例如"encoding/base64"PkgPath() string// 返回类型大小,比如int占8字节Size() uintptr// 返回最段的类型,例如”base64“而不是"encoding/base64"String() string// 返回类型的数字枚举Kind() Kind// 返回u类型是否实现了接口Implements(u Type) bool// 当前类型的值是否可以赋值为u类型AssignableTo(u Type) bool// 当前类型的值是否可以转换为u类型,就算可转换,依然可能会panic。比如数组大小不匹配时进行转换ConvertibleTo(u Type) bool// 此类型是否可比较,返回true在比较时也可能panic,因为interface是可比较的,但是interface的子类可能是不可比较的Comparable() boolBits() intChanDir() ChanDirIsVariadic() bool// 返回此类型的元素类型,必须是Array、Chan、Map、Pointer、Slice类型调用,否则会panicElem() Type// 返回索引为i的结构体类型的字段Field(i int) StructField// 必须是结构体调用,否则会panic。返回嵌套字段FieldByIndex(index []int) StructField// 根据名字获取字段,找到返回trueFieldByName(name string) (StructField, bool)// 根据条件查找字段FieldByNameFunc(match func(string) bool) (StructField, bool)// In returns the type of a function type's i'th input parameter.// It panics if the type's Kind is not Func.// It panics if i is not in the range [0, NumIn()).In(i int) Type// Key returns a map type's key type.// It panics if the type's Kind is not Map.Key() Type// Len returns an array type's length.// It panics if the type's Kind is not Array.Len() int// NumField returns a struct type's field count.// It panics if the type's Kind is not Struct.NumField() int// NumIn returns a function type's input parameter count.// It panics if the type's Kind is not Func.NumIn() int// NumOut returns a function type's output parameter count.// It panics if the type's Kind is not Func.NumOut() int// Out returns the type of a function type's i'th output parameter.// It panics if the type's Kind is not Func.// It panics if i is not in the range [0, NumOut()).Out(i int) Typecommon() *rtypeuncommon() *uncommonType
}

了解反射包下的基本数据结构和方法后,下面开始编程

package mainimport ("fmt""reflect""strconv"
)// 任何类型转打印
func AnyToString(a interface{}) string {// v是Value类型,属性包含a的实际类型+值v := reflect.ValueOf(a)// 判断v的类型switch v.Kind() {case reflect.Invalid: // 无效值return "invalid"case reflect.String: // 字符串return v.String()case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: // 数字类型return strconv.FormatInt(v.Int(), 10)case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: // 无符号数字类型return strconv.FormatUint(v.Uint(), 10)case reflect.Bool: // 布尔类型return strconv.FormatBool(v.Bool())case reflect.Float64, reflect.Float32: // 浮点数类型return strconv.FormatFloat(v.Float(), 'f', -1, 64)case reflect.Ptr: // 指针类型if v.IsNil() {return "<nil>"}// v.Elem()取出指针指向的数据,类型为reflect.Value// v.Elem().Interface()将reflect.Value转为interface{}// AnyToString(v.Elem().Interface()) 递归再次获取字符串return AnyToString(v.Elem().Interface())case reflect.Slice, reflect.Array: // 切片和数组类型s := "["// 获取数组或者切片的长度length := v.Len()for i := 0; i < length; i++ {// v.Index(i)为获取下标为i的reflect.Value类型数据// v.Index(i).Interface() 将reflect.Value转为interface{}// AnyToString(v.Index(i).Interface()) 递归再次获取字符串s += AnyToString(v.Index(i).Interface())if i < length-1 {s += ","}}s += "]"return scase reflect.Map: // 字典类型// 反射获取map的所有keykeys := v.MapKeys()// 获取map的长度length := len(keys)s := "{"for i := 0; i < length; i++ {key := keys[i]// 获取map的valuevalue := v.MapIndex(key)s += fmt.Sprintf("%s", AnyToString(key.Interface())) // 拼接keys += ": "s += AnyToString(value.Interface()) // 拼接valueif i < length-1 {s += ", "}}s += "}"return scase reflect.Struct: // 结构体类型s := "{"count := v.NumField() // 获取结构体的字段数量for i := 0; i < count; i++ {// v.Type().Field(i) s += fmt.Sprintf("%s:%s", v.Type().Field(i).Name, AnyToString(v.Field(i).Interface()))if i < count-1 {s += ","}}s += "}"return sdefault: // 其他类型return fmt.Sprintf("%+v", v)}
}func main() {fmt.Println(AnyToString(1))fmt.Println(AnyToString("字符串"))fmt.Println(AnyToString(3.1415926))fmt.Println(AnyToString(255))fmt.Println(AnyToString([]int{1, 2, 3}))fmt.Println(AnyToString(map[string]int{"age": 1}))account := &Account{Age:  2,Name: "jinnian",}accountList := []Account{{1, "wo"},{0, "c"},}fmt.Println(AnyToString(accountList))fmt.Println(AnyToString(account))fmt.Println(AnyToString(nil))fmt.Println(AnyToString(true))fmt.Println(AnyToString(&accountList))
}

输出

1
字符串
3.1415926
255
[1,2,3]
{age: 1}
[{Age:1,Name:wo},{Age:0,Name:c}]
{Age:2,Name:jinnian}
invalid
true
[{Age:1,Name:wo},{Age:0,Name:c}]

开始学起来吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/746137.shtml

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

相关文章

网络流量监控软件AnaTraf:优化性能、排除故障的最佳选择

目录 导言 网络流量监控的重要性 AnaTraf网络万用表的功能与优势 网络故障排除与优化网络性能 结论 导言 在当今数字化时代&#xff0c;计算机网络已经成为企业和组织的核心基础设施。然而&#xff0c;网络流量的管理和监控对于确保网络性能的稳定和优化至关重要。本文将介…

数码管动态扫描显示

摸鱼记录 Day_16 (&#xff9f;O&#xff9f;) review 前边已经学习了&#xff1a; 串口接收&#xff1a;Vivado 串口接收优化-CSDN博客 1. 今日摸鱼任务 串口接收数据 并用数码管显示 (&#xff9f;O&#xff9f;) 小梅哥视频&#xff1a; 17A 数码管段码显示与动态扫…

使用点链云管家创建瑜伽约课小程序

点链云管家 点链云管家是由上海点链科技开发的门店管理系统&#xff0c;为线下门店商家提供一站式门店运营服务平台解决方案&#xff0c;适用于瑜伽健身、美业、新零售会员制电商、母婴店、宠物店、按摩养生、服装、美容、美甲、汽车服务、商超零售、餐饮、KTV娱乐、干洗等18个…

Python实时追踪关键点组成人体模型

项目背景 最近遇到这样一个需求&#xff1a; 1&#xff1a;实时追踪关键点组成人体模型&#xff08;手臂包括三个点&#xff1a;手腕&#xff0c;肘关节&#xff0c;双肩&#xff1b;腿部包括胯骨&#xff0c;膝盖&#xff0c;脚踝&#xff09; 2&#xff1a;运用追踪到的关键…

数据仓库的设计开发应用(一)

目录 一、数据仓库设计的特点二、数据仓库系统开发过程三、数据仓库系统的规划 一、数据仓库设计的特点 1、“数据驱动” 的设计 数据仓库是从已有数据出发的设计方法&#xff0c;即从数据源抽取数据&#xff0c;经转换形成面向主题&#xff0c;支持决策的数据集合。 以全面了…

Talk|加州大学洛杉矶分校鲁盼:基于大型语言模型的多模态数学推理

本期为TechBeat人工智能社区第579期线上Talk。 北京时间3月14日(周四)20:00&#xff0c;加州大学洛杉矶分校博士生—鲁盼的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “基于大型语言模型的多模态数学推理”&#xff0c;向大家系统地介绍了多模态…

大语言模型智能体简介

大语言模型&#xff08;LLM&#xff09;智能体&#xff0c;是一种利用大语言模型进行复杂任务执行的应用。这种智能体通过结合大语言模型与关键模块&#xff0c;如规划和记忆&#xff0c;来执行任务。构建这类智能体时&#xff0c;LLM充当着控制中心或“大脑”的角色&#xff0…

Compose UI 之 Buttons 按钮 IconButtons 图标按钮

Buttons 按钮 Android Compose UI 库中的 Button 和 IconButton 是两种常用的组件,它们各自具有一些独特的特点。 Button 的特点: 可点击性:Button 是一个可点击的组件,通常用于触发某个操作或事件。文本内容:Button 通常包含文本内容,用于描述按钮的功能或操作。自定义…

【数据结构】模拟实现二叉搜索树

文章目录 1. 二叉搜索树的实现2. 二叉搜索树的应用3. 改造二叉搜索树为 KV 结构4. 二叉搜索树的性能分析 1. 二叉搜索树的实现 namespace key {template<class K>struct BSTreeNode{typedef BSTreeNode<K> Node;Node* _left;Node* _right;K _key;BSTreeNode(const…

YOLOv8独家改进:backbone改进 | 最新大卷积核CNN架构UniRepLKNet,ImageNet 88% | CVPR2024

💡💡💡本文独家改进:大核卷积一统多种模态!RepLK正统续作UniRepLKNet,代替YOLOv8 Backbone 改进结构图如下: 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/category_12511737.html?spm=1001.2014.3001.5482 💡💡💡全网独家首发创新(原创),适…

深度解析HTTP反向代理-okey proxy

反向代理這個概念可能並不常見&#xff0c;但其實它對於提升網路安全和訪問速度方面發揮著很大作用。 HTTP反向代理&#xff08;HTTP Reverse Proxy&#xff09;是一種特殊的代理伺服器&#xff0c;首先它能夠接收互聯網上的連接請求&#xff0c;然後將這些請求轉發給內部網路…

【CSP考点回顾】并查集(1)

并查集 并查集是一种简单而高效的数据结构&#xff0c;主要用于处理一些分离的元素集合的合并与查询问题。它在计算机科学中应用广泛&#xff0c;尤其适用于那些需要动态管理和查询元素分组情况的场景&#xff0c;如网络连接、图的连通分量、社交网络中的群组划分等。通过并查集…

Windows系统搭建Cloudreve结合内网穿透打造可公网访问的私有云盘

目录 ⛳️推荐 1、前言 2、本地网站搭建 2.1 环境使用 2.2 支持组件选择 2.3 网页安装 2.4 测试和使用 2.5 问题解决 3、本地网页发布 3.1 cpolar云端设置 3.2 cpolar本地设置 4、公网访问测试 5、结语 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff…

通讯芯片D3232简介——主要用于工控主板、工业控制器、新能源充电桩等众多涉及RS232通讯的产品。

一、应用领域 D3232芯片主要用于工控主板、工业控制器、程序烧录下载器、仿真器、新能源充电桩等众多涉及RS232通讯的产品。 二、基本特性 D3232芯片由两个线路驱动器、两个线路接收器和双电荷泵电路组成&#xff0c;具有HBM>15kV、CDM>2kV的ESD保护能力&#xff0c;并且…

leetcode解题思路分析(一百五十三)1342 - 1344 题

将数字变成 0 的操作次数 给你一个非负整数 num &#xff0c;请你返回将它变成 0 所需要的步数。 如果当前数字是偶数&#xff0c;你需要把它除以 2 &#xff1b;否则&#xff0c;减去 1 。 直接做就完事 class Solution { public:int numberOfSteps(int num) {int nCnt 0;w…

Java Web项目—餐饮管理系统Day02-管理员后台开发(一)登录

文章目录 1. 创建实体类2. 创建三层调用结构mapperservicecontroller 3. 登录逻辑实现4. 过滤器/拦截器 登录功能开发, 主要是要校验登录账号及密码的准确性, 注意密码使用 base64 加密. 另外一个最重要的是要记住当前用户的id以记住登录状态, 并使用拦截器, 对于部分请求, 需要…

从原理总结chatGPT的Prompt的方法

ChatGPT的Prompt方法是一种引导模型生成对话的技术&#xff0c;它基于前面已经提供的上下文信息&#xff0c;以及一个特定的输入格式来指导模型生成合理、连贯的回答。以下是ChatGPT Prompt方法的原理总结&#xff1a; 输入格式&#xff1a;Prompt方法将对话分为多个轮次&#…

外观模式实战运用

前言 即使在没有学习过设计模式之前&#xff0c;只要是写过代码&#xff0c;都会在不经意间使用到外观模式&#xff0c;或者说用到了外观模式的思想。 外观模式的定义&#xff1a;通过创建一个统一的高层接口&#xff0c;使得复杂的子系统更加容易使用。这个模式为复杂的系统…

Seata 2.x 系列【10】回滚日志表 undo_log

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Seata 版本 2.0.0 本系列Spring Boot 版本 3.2.0 本系列Spring Cloud 版本 2023.0.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 概述2. 表语句…

【Java 并发】AbstractQueuedSynchronizer 中的 Condition

1 简介 任何一个 Java 对象都天然继承于 Object 类, 在线程间实现通信的往往会应用到 Object 的几个方法, 比如 wait(), wait(long timeout), wait(long timeout, int nanos) 与 notify(), notifyAll() 几个方法实现等待 / 通知机制。同样的, 在 Java Lock 体系下也有同样的方…