Go语言的映射reflect使用大全

目录

前言

一、映射的基本用法

1.获取类型信息

2.获取值

3.读取和设置值

4.使用Kind来区分类型

5.操作结构体

6.创建新实例

7.调用方法

8.调用方法

二、使用实例

总结

前言

Go语言作为一个高性能的静态语言,我们在写函数的时候,由于go语言的特性,我们需要定义变量类型,大多情况下,变量类型是固定结构体,这就会导致我们想做一个适配性较高的函数的时候,则需要将变量以及返回值用interface{}接口实现


一、映射的基本用法

1.获取类型信息

使用`reflect.TypeOf()`可以获取任何值的类型信息

var x float64 = 3.4
fmt.Println("type:", reflect.TypeOf(x))

2.获取值

使用`reflect.ValueOf()`可以获取reflect.Value类型表示的实际值:

var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("value:", v)
fmt.Println("type:", v.Type())
fmt.Println("kind:", v.Kind())

3.读取和设置值

通过reflect可以对变量的值进行读取和设置:

var x float64 = 3.4
p := reflect.ValueOf(&x) // 注意这里必须要传递x的地址
v := p.Elem()
v.SetFloat(7.1)

4.使用Kind来区分类型

`reflect.Kind`可以用来区分基本类型:

v := reflect.ValueOf(x)
if v.Kind() == reflect.Float64 {// x是float64类型
}

5.操作结构体

可以通过`reflect`包来动态地读取和设置结构体的字段,甚至可以调用方法:

type MyStruct struct {Field1 intField2 string
}s := MyStruct{Field1: 10, Field2: "Hello"}
v := reflect.ValueOf(s)
typeOfS := v.Type()for i := 0; i < v.NumField(); i++ {field := v.Field(i)fmt.Printf("%d: %s %s = %v
", i, typeOfS.Field(i).Name, field.Type(), field.Interface())
}

6.创建新实例

type MyStruct struct {Field1 int
}var msType reflect.Type = reflect.TypeOf(MyStruct{})
msValue := reflect.New(msType).Elem()
msValue.Field(0).SetInt(10)

7.调用方法

//动态调用方法v := reflect.ValueOf(s)
m := v.MethodByName("MethodName")
args := []reflect.Value{reflect.ValueOf(arg1), reflect.ValueOf(arg2)}
result := m.Call(args)

8.调用方法

对于映射、切片和数组类型,`reflect`包提供了额外的函数来动态操作它们;例如可以通过`reflect.Append`、`reflect.MakeSlice`等创建和操作切片:

a := []int{1,2,3}
v := reflect.ValueOf(a)
newValue := reflect.Append(v, reflect.ValueOf(4))
fmt.Println(newValue.Interface()) // [1 2 3 4]

二、使用实例

在GIN+GROM框架中我建立了一个表模板

type TempGeo struct {BSM  string `gorm:"type:varchar(255);primary_key"`TBMJ float64MAC  string `gorm:"type:varchar(255)"`Name string `gorm:"type:varchar(255)"`Date string `gorm:"type:varchar(255)"`Geom string `gorm:"type:geometry(MultiPolygon,4326)"`
}

我写了一个接口,想将这个表转换为Geojson

func (uc *UserController) ShowTempGeo(c *gin.Context) {bsm := c.Query("bsm")var mytable []models.TempGeoDB := models.DBDB.Where("bsm = ?", bsm).Find(&mytable)data := methods.MakeGeoJSON(mytable)c.JSON(http.StatusOK, data)
}

其中的MakeGeoJSON函数就是使用了映射实现的,如果不使用映射,就会出现如果我重新造一个表,那么我就需要重写一个MakeGeoJSON函数并新定义变量,这是静态语言很麻烦的一个事情,还好go在这方面有一个映射的口子,让我们能写出泛用性函数。以下代码就是将数据都通过映射实现。

func MakeGeoJSON(items interface{}) interface{} {var FeaturesList []*geojson.FeatureFeaturesList = []*geojson.Feature{}var sliceValue reflect.Valueif reflect.TypeOf(items).Kind() == reflect.Slice {sliceValue = reflect.ValueOf(items)} else {sliceValue = reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(items)), 1, 1)sliceValue.Index(0).Set(reflect.ValueOf(items))}for i := 0; i < sliceValue.Len(); i++ {t := sliceValue.Index(i).Interface()v := reflect.ValueOf(t)tt := reflect.TypeOf(t)geomField := v.FieldByName("Geom")if !geomField.IsValid() {continue}geomStr, _ := geomField.Interface().(string)properties := make(map[string]interface{})for i := 0; i < v.NumField(); i++ {if tt.Field(i).Name != "Geom" {properties[strings.ToLower(tt.Field(i).Name)] = v.Field(i).Interface()}}wkbBytes, _ := hex.DecodeString(strings.Trim(geomStr, "  "))geom, _ := wkb.Unmarshal(wkbBytes)feature := geojson.NewFeature(geom)feature.Properties = propertiesFeaturesList = append(FeaturesList, feature)}features := geojson.NewFeatureCollection()features.Features = FeaturesListGeoJSON, _ := json.Marshal(features)var obj interface{}json.Unmarshal(GeoJSON, &obj)return obj
}

总结

        在Go语言中,`reflect`包被用来在运行时动态地操作对象。尽管这个包非常强大,但是它通常不建议用于日常编程,因为它会使代码更难理解和维护,同时也会减慢程序运行速度。但是当你需要编写通用代码或者框架,或者需要处理未知类型的数据时,`reflect`  包就显得非常有用。

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

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

相关文章

工业相机与镜头参数及选型

文章目录 1、相机成像系统模型1.1 视场1.2 成像简化模型 2、工业相机参数2.1 分辨率2.2 靶面尺寸2.3 像元尺寸2.4 帧率/行频2.5 像素深度2.6 动态范围2.7 信噪比2.8 曝光时间2.9 相机接口 3、工业镜头参数3.1 焦距3.2 光圈3.3 景深3.4 镜头分辨率3.5 工作距离&#xff08;Worki…

微信小程序入门,学习全局配置与页面配置

目录 一、微信小程序 二、微信小程序的全局配置 三、微信小程序的页面配置 四、全局配置与页面配置的区别 一、微信小程序 微信小程序是一种基于微信平台的应用程序&#xff0c;它可以在微信内部直接运行&#xff0c;无需下载安装。微信小程序具有以下特点和优势&#xff…

Spring Boot自动配置原理

1.SpringBootApplication注解 springboot是基于spring的新型的轻量级框架&#xff0c;最厉害的地方当属**自动配置。**那我们就可以根据启动流程和相关原理来看看&#xff0c;如何实现传奇的自动配置 SpringBootApplication//标注在某个类上&#xff0c;表示这个类是SpringBo…

【技术预研】starRocks高性价比替换hbase

hbase作为类列数据库&#xff0c;更准确说是列族数据库。本质上是一个文件查询系统&#xff0c;追求极限的写入和读取。 而starRocks作为olap数据库&#xff0c;在保持优秀的关联计算能力的前提下&#xff0c;还有不错的查询效率&#xff0c;当然和hbase本身比还有一定差距。 但…

<蓝桥杯软件赛>零基础备赛20周--第15周--快速幂+素数

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周。 在QQ群上交流答疑&am…

【设计模式】张一鸣笔记:责任链接模式怎么用?

我将通过一个贴近现实的故事——请假审批流程&#xff0c;带你了解和掌握责任链模式。 什么是责任链模式&#xff1f; 责任链模式是一种行为设计模式&#xff0c;它让你可以避免将请求的发送者与接收者耦合在一起&#xff0c;让多个对象都有处理请求的机会将这个对象连成一条…

python基础教程九 抽象二(函数参数)

1. 值从哪里来 定义函数时&#xff0c;你可能心存疑虑&#xff0c;参数的值是怎么来的呢&#xff1f; 在def语句中&#xff0c;位于函数名后面的变量通常称为形式参数&#xff0c;在调用函数时提供的值称为实参&#xff0c;但在本书不做严格区分。 2. 我能修改参数吗 函数通…

同样是IT行业,测试和开发薪资真就差这么大吗?

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

Java进阶之旅第六天

Java进阶之旅第六天 Stream流 Stream的思想 Stream流中引入函数式编程的思想,以类似流水线的方式处理数据,使得代码更加高效整洁Stream中提供并行处理的能力,可以将数据分成多个子任务,并行处理 各类型的调用方法 类型方法说明单列集合default Stream streamCollection中默…

请写出js中的两种定时器,区别是什么?怎么清除定时器?

在JavaScript中有两种常用的定时器&#xff1a;setTimeout 和 setInterval。 setTimeout&#xff1a;此函数用于在指定的毫秒数后执行一次函数或计算出的表达式。例如&#xff0c;如果你想在5秒后打印一条消息&#xff0c;你可以这样做&#xff1a; var myTimer setTimeout(f…

下载csdn文章,并保存md笔记中的图片链接至本地

推荐1个下载别人csdn文章笔记的java项目&#xff1a;csdn-blog2markword-downloader 拿到别人的md笔记后&#xff0c;但是笔记中的图片又是以链接的格式给的&#xff0c;这个链接说不定后面就失效了&#xff0c;笔记也就看不到图片了。手动右键也可以保存图片&#xff0c;但是…

前端学习笔记 7:小兔鲜

前端学习笔记 7&#xff1a;小兔鲜 准备工作 创建项目 创建项目&#xff1a; npm init vuelatest相关选项如下&#xff1a; 在src目录下添加以下目录&#xff1a; 别名路径联想 默认情况下在 VSCode 中输入import xxx from ...时不会启用路径联想功能&#xff0c;要启用需…

使用宝塔面板安装wiki.js详细教程

因为在安装过程中遇到了一些问题&#xff0c;花费了很长时间在解决问题上。根据这篇教程可以少踩很多坑。点赞加关注吧。 准备运行环境 Nodejs 在宝塔面板的软件商店中找到nodejs版本管理器并安装。 点击设置&#xff0c;选择一个稳定版安装。 PostgreSQL 官方推荐的数据库是…

用户洞察:精准解读用户的真实需求!

洞察用户需求的过程和谈恋爱一样。你不能简简单单地问客户&#xff0c;你想要什么&#xff1f;你有什么痛点&#xff1f;这样的问法是无法得到任何有价值的信息。这就好比谈恋爱的场景&#xff0c;如果你问对方想吃什么&#xff0c;大概率会得到“随便”“都行”这类的答案&…

Python实现一个简单的烟花秀效果(附带源码)

在 Python 中实现一个简单的烟花秀效果&#xff0c;可以使用 turtle 模块进行绘图。以下是一个简单的例子&#xff1a; import turtle import random import math# 设置画布 turtle.speed(0) turtle.hideturtle() turtle.bgcolor("black")def create_firework(x, y)…

力扣62. 不同路径

动态规划 思路&#xff1a; 定义 dp[r][c] 为到达坐标 (r, c) 的路径数&#xff1a; 它只能有同一行左边相邻方格向右到达或者同一列上方相邻方格向下到达&#xff1b;状态转移方程&#xff1a; dp[r][c] dp[r][c - 1] dp[r - 1][c]初始状态 dp[0][0] 1第一行的路径数是 1第…

2526. 随机数生成器(BSGS,推导)

题目路径&#xff1a; https://www.acwing.com/problem/content/2528/ 思路&#xff1a;

HNU-数据挖掘-实验1-实验平台及环境安装

数据挖掘课程实验实验1 实验平台及环境安装 计科210X 甘晴void 202108010XXX 文章目录 数据挖掘课程实验<br>实验1 实验平台及环境安装实验背景实验目标实验步骤1.安装虚拟机和Linux平台&#xff0c;熟悉Ubuntu环境。2.在Linux平台上搭建Python平台&#xff0c;并安装…

esp32-idf eclipse 分区表(partition table / NVS)的读写demo

前言&#xff1a; 分区表&#xff08;Partition Table&#xff09;和 NVS&#xff08;Non-Volatile Storage&#xff09;是 ESP-IDF 中用于存储数据的两种不同机制。 分区表&#xff08;Partition Table&#xff09;&#xff1a; 分区表定义了将 Flash 存储器划分为不同逻辑分…

RT-DETR 模型改进 | AKConv:具有任意采样形状和任意参数数量的卷积核

基于卷积操作的神经网络在深度学习领域取得了显著的成果,但标准卷积操作存在两个固有缺陷。一方面,卷积操作受限于局部窗口,无法捕捉其他位置的信息,而其采样形状是固定的。另一方面,卷积核的大小固定为kk,呈固定的正方形形状,而参数数量往往随大小呈平方增长。显然,不…