golang 对不同结构体中数据进行相互转换的几种常用方法

常用的不同结构体中的数据相互转换的方法

1. 利用json包的marshal和unmarshal

要求:json标签的值必须一致
示例:

package main
import ("encoding/json""fmt"
)
type A struct {Name string `json:"name"`Age int `json:"age"`Gender string `json:"gender"`
}
type B struct {Name string `json:"name"`Age int `json:"age"`Weight string `json:"weight"`
}func main() {a:=A{Name:   "小可",Age:    121,Gender: "男",}var b BjsonBytes,_:=json.Marshal(a)err:=json.Unmarshal(jsonBytes,&b)if err!=nil{fmt.Println(err.Error())}else{fmt.Printf("%+v",b)}
}

输出:

{Name:小可 Age:121 Weight:}

2. 使用第三方包 copier 进行数据转换

要求:结构体的数据结构和字段名必须一致

go get github.com/jinzhu/copier

使用示例

import ("fmt""github.com/jinzhu/copier"
)func main() {a:=A{Name:   "小可",Age:    121,Gender: "男",}var b Berr := copier.Copy(&a, &b)if err!=nil{fmt.Println(err.Error())}else{fmt.Printf("%+v",b)}
}

对字段名相同,但是数据类型不同的字段,可以像这样额外添加option去转换

// time.Time 和 string 之间相互转换的方法
var CopierProtoOptions = copier.Option{IgnoreEmpty: true,DeepCopy:    true,Converters: []copier.TypeConverter{{SrcType: time.Time{},DstType: copier.String,Fn: func(src interface{}) (interface{}, error) {s, ok := src.(time.Time)if !ok {return nil, errors.New("src type :time.Time not matching")}return s.Format("2006-01-02 15:04:05"), nil},},{SrcType: copier.String,DstType: time.Time{},Fn: func(src interface{}) (interface{}, error) {s, ok := src.(string)if !ok {return nil, errors.New("src type :time.Time not matching")}tt, err := time.ParseInLocation(s, "2006-01-02 15:04:05", shanghai)return tt, err},},},
}

使用

type A struct {Name string Age intGender string BirthDay string 
}
type B struct {Name string Age intWeight stringBirthDay time.time
}func main() {a:=A{Name:   "小可",Age:    121,Gender: "男",BirthDay :"1997-05-08 11:20:11",}var b Berr := copier.CopyWithOption(&a, &b,CopierProtoOptions)if err!=nil{fmt.Println(err.Error())}else{fmt.Printf("%+v",b)}
}

3.对结构不同的结构体进行转换

举例有如下结构体,需要把DataRequest中的数据转换到ProtoRequest 中。特点是,ProtoRequest 中,定义了一个Query字段来继承*CommonQuery类型。

type CommonQuery struct {Id   intName string
}
type DataRequest struct {CommonQueryPage     int64 `json:"page"`PageSize int64 `json:"pageSize"`
}
type ProtoRequest struct {Query    *CommonQuery `json:"query"`Page     int64        `json:"page"`PageSize int64        `json:"pageSize"`
}

此时需要自定义一个方法,示例如下,大家可以参考下面的代码进行适当修改。

var shanghai, _ = time.LoadLocation("Asia/Shanghai")
func ConvertData(from interface{}, to interface{}) {var proxyField = "Query"fromValue := reflect.ValueOf(from)toValue := reflect.ValueOf(to)toType := reflect.TypeOf(to)// 获取From结构体的字段信息fromType := fromValue.Type().Elem()for i := 0; i < fromType.NumField(); i++ {// 获取字段名和字段值fieldName := fromType.Field(i).NamefieldValue := fromValue.Elem().FieldByName(fieldName)if fieldName != proxyField {_, exists := toType.Elem().FieldByName(fieldName)if exists {// 设置To结构体中相应字段的值toValue.Elem().FieldByName(fieldName).Set(fieldValue)}}}queryField, exists := toType.Elem().FieldByName(proxyField)if exists {var queryFieldTypeName string// 指针类型额外处理,拿到真实的数据类型if queryField.Type.Kind() == reflect.Ptr {queryFieldTypeName = queryField.Type.Elem().String()} else {queryFieldTypeName = queryField.Type.Kind().String()}//处理拿到的结构体类型如 utils.xxxx的类型,去掉utils.这部分if strings.Contains(queryFieldTypeName, ".") {queryFieldTypeName = strings.Split(queryFieldTypeName, ".")[1]}fromQueryValue := fromValue.Elem().FieldByName(queryFieldTypeName)if fromQueryValue.IsValid() && fromQueryValue.CanAddr() {toValue.Elem().FieldByName(proxyField).Set(fromQueryValue.Addr())}}
}

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

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

相关文章

【开发篇】九、SpringBoot整合ES(ElasticSearch)

文章目录 1、整合2、简单示例3、一点补充4、增删改查索引与文档 1、整合 整合思路都一样&#xff0c;先起步依赖或普通依赖&#xff0c;再配置&#xff0c;再封装的操作对象。先引入依赖&#xff1a; <dependency> <groupId>org.springframework.boot</grou…

基于Java的电影评论网站设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于Java的电影评论网站…

内存泄漏,内存溢出,抽象类和接口,netstat、ping、ifconfig的区别

持续学习是我们必备的技能之一&#xff0c;保持与时俱进&#xff0c;保持行业的敏感度&#xff0c;关注行业发展趋势&#xff0c;了解新技术&#xff0c;加强自己的认知&#xff0c;积极的应对变化 内存泄漏 memory leak 是指程序在申请内存后&#xff0c;无法释放已申请的内…

Oracle去重去空

1. -- 去重函数 DISTINCT SELECT DISTINCT E.JOB FROM EMP E -- 只能放在 SELECT 后面,或 函数的括号里面 2. -- 分组去重 SELECT E.JOB FROM EMP E GROUP BY E.JOB -- 去空值 NVL (字段,默认值) -- 空值特性: 1. 空值和任何值进行算术运算都为空 2. 空值跟任何进行…

Linux centos7压缩包安装mysql-8.0.34 并设置开机自启

下载安装解包 并解压 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.34-linux-glibc2.12-x86_64.tar.xztar -xf mysql-8.0.34-linux-glibc2.12-x86_64.tar.xzmv mysql-8.0.34-linux-glibc2.12-x86_64 /usr/local/mysql初始化数据及安装操作 配置mysql配置文…

IntelliJ IDEA - Maven 在控制台Maven编译正常,但是在IDEA中不正常,表现不一致

文章目录 现象原因解决验证 现象 一个Maven项目&#xff0c;当导入到IDEA后&#xff0c;无法在IDEA中正常的编译和下载jar依赖&#xff0c;类似下面的截图。 但是在Windows控制台却可以正常编译&#xff0c;类似下面的截图。 CMD执行&#xff1a;mvn clean install -Dmaven.te…

水库河道生态流量监测系统的主要内容

一、系统背景 我国为保护河流生态环境&#xff0c;推动水资源科学、合理、有序开发和可持续利用&#xff0c;各地水利和环保部门相继出台措施对不满足生态流量下泄要求的水电站责令整改或挂牌督办。近几年几百家水库在各个主要流域建成&#xff0c;由于缺乏对各个水库生态下泄流…

蓝牙核心规范(V5.4)11.5-LE Audio 笔记之Context Type

专栏汇总网址:蓝牙篇之蓝牙核心规范学习笔记(V5.4)汇总_蓝牙核心规范中文版_心跳包的博客-CSDN博客 爬虫网站无德,任何非CSDN看到的这篇文章都是盗版网站,你也看不全。认准原始网址。!!! 蓝牙中的上下文类型(Context Type)是用于描述音频流当前使用情况或相关使用情…

【Java】集合 之 使用List

在集合类中&#xff0c;List是最基础的一种集合&#xff1a;它是一种有序列表。 List的行为和数组几乎完全相同&#xff1a;List内部按照放入元素的先后顺序存放&#xff0c;每个元素都可以通过索引确定自己的位置&#xff0c;List的索引和数组一样&#xff0c;从0开始。 数组…

为什么说软文能够扩大中小企业的品牌影响力?

在当今的商业环境中&#xff0c;品牌影响力对于企业的成功至关重要。对于中小企业来说&#xff0c;利用软文来打造品牌影响力是一种成本低且效果更高的方式。为什么说软文能够扩大中小企业的品牌影响力呢&#xff1f;下面就让媒介盒子告诉你。 一、塑造品牌形象 首先&#xff…

走心分享!天津诚筑说Java大数据培训我该如何选择?

随着互联网的发展&#xff0c;IT行业变得越来越炙手可热&#xff0c;其中较为火热的当属大数据和Java了&#xff0c;许多学员都很纠结&#xff0c;Java和大数据我应该如何选择呢?今天小编带大家了解一下Java和大数据之间的区别&#xff01; Java和大数据的关系 Java是一种面…

Verilog中什么是断言?

断言就是在我们的程序中插入一句代码&#xff0c;这句代码只有仿真的时候才会生效&#xff0c;这段代码的作用是帮助我们判断某个条件是否满足&#xff08;例如某个数据是否超出了范围&#xff09;&#xff0c;如果条件不满足&#xff08;数据超出了范围&#xff09;&#xff0…

搭建安信可小安派Windows 开发环境

搭建小安派Windows 开发环境 Ai-Pi-Eyes 系列是安信可开源团队专门为Ai-M61-32S设计的开发板&#xff0c;支持WiFi6、BLE5.3。所搭载的Ai-M61-32S 模组具有丰富的外设接口&#xff0c;具体包括 DVP、MJPEG、Dispaly、AudioCodec、USB2.0、SDU、以太网 (EMAC)、SD/MMC(SDH)、SP…

Mojo:新AI语言中的7个惊人的Python升级

一、说明 AI发展是日新月异的&#xff0c;对于新模型的产生&#xff0c;我们不能不给以关注。Mojo就是一种新发布的编程语言&#xff0c;专为AI开发人员制作&#xff0c;由Modular制作&#xff0c;Modular是一家由Swift的原始创建者Chris Lattner创立的公司。 二、关于MOJO的概…

人生第一个项目(学生管理系统)(进阶版)

题目: package Project.Student_system_upper版;public class 题目学生股那里系统upper {//增删改查可以直接参照之前的文件代码(cv大法)/* 为学生管理系统写一个登录,注册,忘记密码的功能只有用户登陆成功之后,才能进入到学生管理系统中进行相应操作*//*分析:1. 登陆界面需要…

notepad编辑器的使用

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言 前言 认知有限&#xff0c;望大家多多包涵&#xff0c;有什么问题也希望能够与大家多交流&#xff0c;共同成长&#xff01;…

vue实现移动端悬浮可拖拽按钮

需求&#xff1a; 按钮在页面侧边悬浮显示&#xff1b;点击按钮可展开多个快捷方式按钮&#xff0c;从下向上展开。长按按钮&#xff0c;则允许拖拽来改变按钮位置&#xff0c;按钮为非展开状态&#xff1b;按钮移动结束&#xff0c;手指松开&#xff0c;计算距离左右两侧距离…

forEach中return会退出循环吗 (改)

原文地址如下&#xff0c;有需要的朋友可以关注 forEach中return会退出循环吗 &#xff08;改&#xff09; (qq.com) forEach循环 在JavaScript中的forEach循环中使用return语句,并不会退出或终止循环,forEach循环会继续执行完剩余的所有迭代。 forEach循环中的return语句只…

使用Docker快速搭建基础服务

Docker安装 #Linux安装 curl -fsSL get.docker.com -o get-docker.sh sudo sh get-docker.sh --mirror Aliyun #启动docker服务 systemctl start docker #将docker添加到开机自启动 sudo systemctl enable docker #查看是否成功安装 docker infoMysql安装 #拉取镜像 docker p…

uniapp使用scroll-into-view实现锚点定位和滚动监听功能【楼层效果 / 侧边导航联动效果】

大佬网址&#xff1a; https://blog.csdn.net/weixin_47136265/article/details/132303570 效果 代码 <template><view class"main"><scroll-view scroll-y"true" class"left-content"><view class"left-item"…