与ChatGpt聊天,学习golang标签的反射机制

news2024/11/17 10:51:26

与ChatGpt聊天,学习golang标签的反射机制

ChatGPT火了以后,本拐先是恐惧,之后是拥抱。

最近很多编程知识的学习,都是通过 chatgpt来搞定。

众所周知,本拐就是一个啥技术都半斤八两的程序员,这次,为了学习golang中一些反射的机制,主要是tag属性,本拐又与chatgpt来了一次深入交流。

过程

本拐确实对golang中的tag属性所知甚少,所以先从json开始吧,挖个坑先。



 golang 中怎么用反射取到json

在 Golang 中,可以使用反射机制来获取一个对象的 json 表示。假设我们有一个结构体 Person 如下:

type Person struct {
    Name    string    `json:"name"`
    Age     int       `json:"age"`
    Address string    `json:"address"`
}

然后,我们可以使用以下代码来将一个 Person 对象转换成 json 字符串,并使用反射机制获取它:

import (
    "encoding/json"
    "reflect"
)

func main() {
    person := Person{"John", 30, "123 Main St."}

    // 将 person 转换为 json 字符串
    jsonBytes, _ := json.Marshal(person)
    jsonString := string(jsonBytes)

    // 通过反射获取 json 中的字段值
    value := reflect.ValueOf(person)
    for i := 0; i < value.NumField(); i++ {
        field := value.Type().Field(i)
        fieldName := field.Tag.Get("json")
        fieldValue := value.Field(i).Interface()
        fmt.Printf("%s: %v\n", fieldName, fieldValue)
    }
}

输出将会是:

name: John
age: 30
address: 123 Main St.

在这个例子中,我们使用 encoding/json 包将 person 对象转换为 json 字符串。然后,我们使用 reflect 包获取结构体的值,通过循环遍历所有字段并使用 Tag.Get 方法获取字段的 json 标签,最后使用 Field(i).Interface() 获取字段的值

56d787e8896cd6dab354bbe131e4cab7.jpeg




嘿嘿,这个问题回答的可不漂亮啊,本拐成功抓住了其中的不足。

 这个方式是不是有些性能损失?因为 json.Marshal(person) 时已经读取了一次

chatgpt成功地get到了我的点。

 是的,您是正确的。在上面的示例中,我们先将 person 对象转换为 JSON 字符串,然后再通过反射机制解析该字符串,这样可能会导致一些性能损失。

如果您需要获取结构体字段的 JSON 标签,而不必将整个结构体转换为 JSON 字符串,您可以使用 reflect 包中的 Type 方法来获取结构体类型,并通过 Type 方法中的 Field 方法获取字段的类型信息。然后,您可以使用 StructTag 方法获取该字段的标签信息,进而获取 JSON 标签。

下面是一个示例:

import (
    "reflect"
)

func main() {
    person := Person{"John", 30, "123 Main St."}

    t := reflect.TypeOf(person)
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        jsonTag := field.Tag.Get("json")
        fmt.Printf("%s: %s\n", field.Name, jsonTag)
    }
}

在这个示例中,我们使用 reflect 包中的 Type 方法获取 person 对象的类型信息,并通过 Type 方法中的 Field 方法获取字段的类型信息。然后,我们使用 StructTag 方法获取该字段的标签信息,并通过 Tag.Get 方法获取 JSON 标签。

这种方法避免了将整个结构体转换为 JSON 字符串的开销,因此可能会更加高效。

c0a4a5c001061150248ec1467d534c60.jpeg


本拐毕竟是乱炖程序员,所以,优化还是要有的。

 如果 这个方法被反复调用,加map是否可以提高他的性能

ChatGPT 一如既往的聪明

 如果您需要在多个不同的地方反复获取结构体字段的 JSON 标签,可以考虑将字段的 JSON 标签缓存到一个 map 中,以提高性能。这样,当需要获取 JSON 标签时,只需要从缓存中查找即可,而不需要每次都使用反射获取。

下面是一个示例:

import (
    "reflect"
)

var jsonTagCache = make(map[string]string)

func getJSONTag(field reflect.StructField) string {
    if jsonTag, ok := jsonTagCache[field.Name]; ok {
        return jsonTag
    }

    jsonTag := field.Tag.Get("json")
    jsonTagCache[field.Name] = jsonTag

    return jsonTag
}

func main() {
    person := Person{"John", 30, "123 Main St."}

    t := reflect.TypeOf(person)
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        jsonTag := getJSONTag(field)
        fmt.Printf("%s: %s\n", field.Name, jsonTag)
    }
}

在这个示例中,我们定义了一个全局变量 jsonTagCache,它是一个 map[string]string 类型的缓存。然后,我们定义了一个函数 getJSONTag,该函数接受一个 reflect.StructField 类型的参数,并返回该字段的 JSON 标签。在该函数中,我们首先从缓存中查找 JSON 标签,如果找到了就直接返回,否则就使用 Tag.Get 方法获取 JSON 标签,并将其添加到缓存中,然后返回 JSON 标签。

在 main 函数中,我们使用 reflect 包中的 Type 方法获取 person 对象的类型信息,并通过 Type 方法中的 Field 方法获取字段的类型信息。然后,我们调用 getJSONTag 函数获取字段的 JSON 标签。

通过缓存 JSON 标签,可以避免每次都使用反射获取标签的开销,因此可以提高性能。但是请注意,如果您在处理的结构体类型非常多,缓存可能会占用大量内存。如果您需要处理大量的结构体类型,请考虑限制缓存的大小或使用 LRU 缓存等方式来优化缓存的性能和内存使用。

e1f6a5f01fff569ea9bcb885376af679.jpeg


好了,终极目的要达成了,问一下自定义标签的问题。

 我如果 把json换成我的一个自定义标签,比如neo4j-colum 是不是也可以用类似的机制来实现类似功能。

 是的,您可以使用类似的机制来获取结构体字段的自定义标签,例如 neo4j-column 标签。

只需要将 getJSONTag 函数中的 Tag.Get("json") 方法替换为 Tag.Get("neo4j-column") 即可。具体来说,您可以按照以下方式修改 getJSONTag 函数:

func getCustomTag(field reflect.StructField, tagName string) string {
    cacheKey := fmt.Sprintf("%s_%s", field.Name, tagName)
    if tag, ok := customTagCache[cacheKey]; ok {
        return tag
    }

    tag := field.Tag.Get(tagName)
    customTagCache[cacheKey] = tag

    return tag
}

在这个示例中,我们将 getJSONTag 函数重命名为 getCustomTag,并将 Tag.Get("json") 方法替换为 Tag.Get(tagName) 方法,其中 tagName 是您要获取的自定义标签名称。我们还修改了缓存键的生成方式,将字段名和标签名组合在一起作为缓存键,以避免不同的标签名使用相同的缓存键。

您可以按照以下方式使用 getCustomTag 函数来获取结构体字段的 neo4j-column 标签:

person := Person{"John", 30, "123 Main St."}

t := reflect.TypeOf(person)
for i := 0; i < t.NumField(); i++ {
    field := t.Field(i)
    columnTag := getCustomTag(field, "neo4j-column")
    fmt.Printf("%s: %s\n", field.Name, columnTag)
}

在这个示例中,我们使用 getCustomTag 函数获取字段的 neo4j-column 标签。

ae817228688df30a52d281376a6adfad.jpeg

注意这里,chatgpt自动纠正了错误的拼写

结论

ChatGPT火了以后,很多朋友说这个东西没有什么用,或是用处不大。

本拐以为,用好这个东西,在于提问的技巧,所以,用这个文章做了一个引子。

您觉得如何?

关于老拐瘦

中年争取不油不丧积极向上的码农一名

咖啡,摄影,骑行,音乐

样样通,样样松

喜欢可以关注一下公众号 

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

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

相关文章

05服务发现:引入etcd服务注册中心

在分布式微服务架构中,服务注册发现组件(通常称为服务注册中心)往往有着举足轻重的作用,它的性能与稳定可能会直接影响到整个服务的状态,比如Spring Cloud中的Eureka、Dubbo中的Zookeeper等等,接下来我们就gRPC微服务中最常见的服务注册中心etcd,来讲述下两者在具体是怎…

Mr. Cappuccino的第41杯咖啡——Kubernetes之Pod调度策略

Kubernetes之Pod调度策略Pod的4种调度策略定向调度nodeNamenodeSelector亲和性调度node亲和性硬限制软限制关系运算符pod亲和性pod反亲和性污点和容忍污点&#xff08;taints&#xff09;容忍&#xff08;tolerations&#xff09;默认情况下&#xff0c;Scheduler计算出一个Pod…

conda 搭建tensorflow-GPU和pycharm以及VS2022 软件环境配置

conda 搭建tensorflow-GPU和pycharm以及VS2022 软件环境配置一、TensorFlow 环境配置安装1. Anaconda下载安装2.conda创建tensorflow环境二、pycharm以及VS2022 环境配置2.1 pycharm 软件安装以及环境配置2.2.1 pycharm 软件安装2.2.2 pycharm 软件conda环境配置2.2 Visual Stu…

注意!华为折叠屏手机的原厂膜不能自己撕!

对于用惯了直板手机的朋友来说&#xff0c;新机开箱撕膜是一件十分有“仪式感”的事情&#xff0c;但是对于折叠屏手机来说&#xff0c;这样的操作万万不可。华为折叠屏手机在使用的过程中也有着和传统智能手机不一样的注意事项&#xff0c;下面这几点大家在入手折叠屏手机之后…

如何利用Power Virtual Agents机器人进行设备维修登记

今天我们来介绍如何利用PVA聊天机器人进行设备维修登记。设计思路是在PVA聊天机器人的对话框中输入“设备维修”触发短语后进行设备维修登记&#xff0c;然后通过自动化流程将维修信息存入到Lists中并通过邮件的形式发送给负责设备维修的人员。 首先&#xff0c;在PVA聊天机器人…

【yolov5】将标注好的数据集进行划分(附完整可运行python代码)

问题描述 准备使用yolov5训练自己的模型&#xff0c;自己将下载的开源数据集按照自己的要求重新标注了一下&#xff0c;然后现在对其进行划分。 问题分析 划分数据集主要的步骤就是&#xff0c;首先要将数据集打乱顺序&#xff0c;然后按照一定的比例将其分为训练集&#xf…

【Blender】使用Blender渲染一段360度旋转的动画

目录一、前言二、方法描述三、渲染设置四、结果一、前言 本文主要讲述了如何使用Blender渲染一段物体360度旋转的动画。 渲染好的效果如下&#xff1a; 二、方法描述 第一步&#xff1a;shiftA&#xff0c;我们在Blender里新建一个平面 第二步&#xff1a;摁s键(scale)&…

(三十五)Vue之过渡与动画

文章目录概述单元素/组件的过渡CSS动画CSS过渡多元素/组件的过渡集成第三方动画Animate上一篇&#xff1a;&#xff08;三十四&#xff09;Vue之新生命周期钩子nextTick 概述 Vue 在插入、更新或者移除 DOM 时&#xff0c;提供多种不同方式的应用过渡效果。包括以下工具&…

PyTorch常用的损失函数(ChatGPT)

L1Loss nn.L1Loss 也称为平均绝对误差&#xff08;Mean Absolute Error&#xff0c;MAE&#xff09;。它计算预测值与真实值之间的差异&#xff08;即误差&#xff09;&#xff0c;然后取绝对值并求和&#xff0c;最后除以样本数量得到平均误差。具体来说&#xff0c;对于一批…

萌新应该如何开始学习走向自动化测试高薪岗位?

对于测试人员来说&#xff0c;不管进行功能测试还是自动化测试&#xff0c;还是性能测试&#xff0c;都是需要编写测试用例&#xff0c;所以我们必须先要了解清楚手工测试用例与自动化测试用例的一些特点&#xff0c;才能更好的开展自动化测试工作。1.1手工测试用例和自动化测试…

最新中文版Studio One6音乐制作DAW工具

你现在用的是什麽 DAW&#xff1f;大家常常在说的 DAW &#xff0c;就是指数位音乐工作站软件&#xff0c;像是常见的 Ableton、Logic、Protools、Cubase 等等&#xff0c;这些都算是 DAW。以上的例子&#xff0c;他们的完整版几乎都是需要花费购买的&#xff0c;当然也有一些免…

【Go基础】Socket和WebSocket编程

文章目录一、Socket编程1. 网络通信过程2. TCP CS架构2.1 网络通信模型2.2 TCP协议解读2.3 Go TCP编程3. UDP CS架构3.1 UDP协议解读3.2 Go UDP编程二、WebSocket编程1. WebSocket协议解读2. WebSocket CS架构实现3. 聊于室实现一、Socket编程 1. 网络通信过程 DMA&#xff1a…

Elasticsearch - Configuring security in Elasticsearch 开启用户名和密码访问

文章目录概述实操Step 1 验证当前版本是否支持安全功能Step 2 打开安全设置Step 3 配置节点间通讯传输的安全性创建证书颁发机构为Elasticsearch集群中的节点生成证书Step 4 修改 elasticsearch.yml配置设置 用户名和密码概述 ES版本&#xff1a; 7.6 官方指导手册&#xff1…

Spring MVC之WebApplicationContext 容器的初始化

简介因为 spring-mvc项目&#xff0c;是 spring-framework的子项目&#xff0c;所以需要拉取 spring-framework整个工程&#xff0c;包含 Spring 所有的子项目前期准备工作源码拉取从 Spring 的 Git 仓库 Fork 项目到自己的 Git 仓库&#xff0c;方便我们在阅读源码的过程中&am…

3年软件测试工作经验裸辞,有点后悔了...

2019年毕业&#xff0c;现在有3年的软件测试工作经验&#xff0c;刚毕业前半年在一家知名上市公司&#xff0c;后面则进入一家传统行业公司待到现在2年半。 由于看不到技术成长以及其他原因&#xff0c;上上周辞职了&#xff0c;目前交接中&#xff0c;下个月中旬就得离开了&a…

基于国产龙芯 CPU 的气井工业网关研究与设计(一)

当前&#xff0c;我国气田的自动化控制程度还未完全普及&#xff0c;并且与世界已普及的气井站的自 动化程度也存在一定的差距。而在天然气资源相对丰富的国家&#xff0c;开采过程中设备研发资 金投入较大&#xff0c;研发周期较长&#xff0c;更新了一代又一代的自动化开采系…

看过来,u盘删除的文件还能找回吗?两种方法,

u盘删除的文件还能找回吗&#xff1f;u盘&#xff0c;全称USB闪存驱动器&#xff0c;它不需物理驱动器&#xff0c;即插即用&#xff0c;且其存储容量远超过软盘&#xff0c;方便携带使用。u盘作为我们常用的存储设备&#xff0c;也是有自己不同功能和划分。以下例举了几种&…

ArcGIS API for JavaScript 4.15系列(8)——Dojo中类的定义

1、前言 JavaScript本质上是基于原型继承的一种编程语言&#xff0c;在ES6标准出现以前&#xff0c;JavaScript定义类的方式往往让人很难理解。而Dojo则很好地解决了这个问题。开发者可以通过dojo/_base/declare模块定义类&#xff0c;也可以通过define引用各个类模块。本文就…

Swift基础语法 - 可选项

可选项&#xff08;Optional&#xff09; 可选项&#xff0c;一般也叫可选类型&#xff0c;它允许将值设置为 nil 在类型名称后面加个问号 ? 来定义一个可选项 var name: String? "CSDN" name nilvar age: Int? //默认就是nil age 30 age nilvar array [2,…

提升电脑运行速度,看这里就够了!

电脑是我们经常使用的工具之一&#xff0c;但是它却很容易出现问题&#xff0c;比如运行速度过慢&#xff0c;那么要如何提升电脑运行速度呢&#xff1f;方法1. 通过系统配置设置启动项1. 按下组合键“WinR”打开“运行”&#xff0c;在运行中输入“msconfig”然后按“回车”。…