Golang结构体值的交换
Golang结构体值的交换
一、添加结构体,多if暴力
最先遇到这个问题是在比编写PUT方法的接口时遇到。
(我公司编写http put方法,是先解析json至StudentInput结构体中,通过if input.Name!=nil来判断是否需要修改原数据的值)
解决方法是增加一个Input struct,该struct字段的变量都为原结构体的指针类型。
优点:可以根据业务逻辑做出改变。
缺点:冗余、易错(每次测试PUT方法时,需要特别小心)。
代码如下:
type Student struct {
ID string `json:"id"
Name string `json:"name"
Age int `json:"age"
}
type StudentInput struct {
ID *string `json:"id" `
Name *string `json:"name"`
Age *int `json:"age" `
}
func Handle() {
var source Student
var input StudentInput
......
if input.Name != nil {
source.Name = *input.Name
}
......
}
这个做法是标准,只是我认为太繁琐想简化一下,参考这篇文章
二、设置tag,利用反射代替多if
最近看了波罗学大佬的一篇文章,突发奇想,可以使用Go的反射实现交换struct中的值。
类似的作品就想到了开源的mapstruct,参考了一下源码,写了一个劣质Demo。
代码如下:
func Swap(source, input interface{}) error {
sourceVal := reflect.ValueOf(source)
inputVal := reflect.ValueOf(input)
if sourceVal.Kind() != reflect.Ptr {
return errors.New("source must be a pointer")
}
if inputVal.Kind() != reflect.Struct {
return errors.New("input must be a struct")
}
defer func() {
if r := recover(); r != nil {
log.Println(r)
return
}
}()
for i := 0; i < inputVal.NumField(); i++ {
for j := 0; j < sourceVal.Elem().NumField(); j++ {
// 零值处理
if inputVal.Field(i).IsZero() {
continue
}
// 比较tag
if tagEqual(sourceVal.Type().Elem().Field(j), inputVal.Type().Field(i)) {
sourceVal.Elem().Field(i).Set(inputVal.Field(j))
break
}
}
}
return nil
}
func tagEqual(s1, s2 reflect.StructField) bool {
return s1.Tag.Get("swapstruct") == s2.Tag.Get("swapstruct")
}
思路很简单,需要修改的字段在tag中增加swapstruct,运用反射查找相同tag修改值。
优点:简单,不容易出错。
缺点:性能较差。
测试代码如下:
type Student struct {
ID string `json:"id" swapstruct:"id"`
Name string `json:"name" swapstruct:"name"`
Age int `json:"age" swapstruct:"age"`
}
func main() {
id := "inputID"
name := "inputName"
//age := 0
input := Student{
ID: id,
Name: name,
//Age: age,
}
source := Student{
ID: "sourceID",
Name: "sourceName",
Age: 22,
}
fmt.Println("source: ", source)
fmt.Println("input: ", input)
if err := Swap(&source, input); err != nil {
log.Println(err)
}
fmt.Println("after: ", source)
}
三、参考
1.mapstructure: https://github.com/mitchellh/mapstructure
2.Go 如何解析 json 内部结构不确定的情况
Golang结构体值的交换的更多相关文章
- golang 结构体中的匿名接口
golang 结构体中的匿名接口 代码示例 golang 中,可以给结构体增加匿名field,可参考 unknwon 大神的书. 匿名字段和内嵌结构体 但,golang同时也可以给结构体定义一个匿名i ...
- golang结构体json格式化的时间格式
golang结构体json格式化的时间格式 在我们开发中,经常会解析time.Time 往往前台传过来的时候,是个string 但是我们希望在结构体转成time.Time type Param str ...
- GO开发[五]:golang结构体struct
Go结构体struct Go语言的结构体(struct)和其他语言的类(class)有同等的地位,但Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性 ...
- golang结构体、接口、反射
struct结构体 struct用来自定义复杂数据结构,可以包含多个字段属性,可以嵌套; go中的struct类型理解为类,可以定义方法,和函数定义有些许区别; struct类型是值类型. struc ...
- golang结构体
声明结构体 定义结构体使用struct关键字.在结构体内部定义它们的成员变量和类型.如果成员变量的类型相同还可以把它们写到同一行. struct里面可以包含多个字段(属性) struct类型可以定义方 ...
- Golang结构体struct的使用(结构体嵌套, 匿名结构体等)
转自: https://studygolang.com/articles/11313 golang中是没有class的,但是有一个结构体struct,有点类似,他没有像java,c++中继承的概念,但 ...
- 【转】golang 结构体和方法
原文:https://www.jianshu.com/p/b6ae3f85c683 ---------------------------------------------------------- ...
- golang 结构体嵌入和匿名成员
考虑一个二维的绘图程序,提供了一个各种图形的库,例如矩形.椭圆形.星形和轮形等几 何形状.这里是其中两个的定义 type Circle struct { X, Y, Radius int } type ...
- [Go] golang结构体成员与函数类型
package main import ( "fmt" ) //定义一个类型 type tsh struct { //定义成员,类型是func() string test func ...
随机推荐
- HDU_2871 线段树+vecor的中间插入和删除使用
本来这个题目就是个合并区间的题,就跟Hotel一样,要插入一段,则找左孩子 合并后的中间区间 右孩子,但是比较恶心的是,他需要实时得到某一段的起终点,或者某个点在第几个段里面,我想过在线段树里面加入几 ...
- OpenResty从入门到开发一个网关服务(使用etcd作为注册中心)
简介 OpenResty(也称为 ngx_openresty)是一个全功能的 Web 应用服务器.它打包了标准的 Nginx 核心,很多的常用的第三方模块,以及它们的大多数依赖项. 通过揉和众多设计良 ...
- POJ 2039:To and Fro
To and Fro Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8632 Accepted: 5797 Descri ...
- POJ 1006:Biorhythms 中国剩余定理
Biorhythms Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 121194 Accepted: 38157 Des ...
- 合并排序_python
#!/usr/bin/python # --coding:utf-8 -- def sort_merge(left,right): i,j=0,0 result=[] while i<len(l ...
- C语言之结构体概述
C语言之结构体概述1.结构体类型是一种自定义类型(1)C语言中有2种类型:原生类型和自定义类型.2.结构体使用时先定义结构体类型再用类型定义变量(1)结构体定义时需要先定义结构体类型,再用类型来定义变 ...
- Python调用OpenCV读显写
OpenCV提供了python的接口,而且很重要的一点是python下的很多接口名与C++的接口名是一样的,这一篇先记录python调用OpenCV去读取图像.显示图像和保存图像. 1.OpenCV读 ...
- Java 接口理解
学习Spring有一段时间了,对java也有了一点了解,最不能理解的就是接口, 即使是写了接口并实现了它,依然无法理解它到底有什么用?看了其他几篇博客,总结了一下自己的理解. 在JAVA编程语言中是一 ...
- linux下springboot项目通过jetty发布war包应用
Linux下jetty发布jar包 1.通过官网下载jetty点击下载https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-distributi ...
- 网鼎杯-Fakebook-反序列化和SSRF和file协议读取文件
0x00知识点:SSRF SSRF (Server-side Request Forge, 服务端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外 ...