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 ...
随机推荐
- linux部分环境搭建
连接数据库: mysql -hrm-uf6b23117l3s5t69zjo.mysql.rds.aliyuncs.com -uwswl -pwswl@2019 显示用户: show databases ...
- 《打造扛得住的MySQL数据库架构》第7章 SQL查询优化
SQL查询优化 7-1 获取有性能问题SQL的三种方法 如何设计最优的数据库表结构 如何建立最好的索引 如何拓展数据库的查询 查询优化,索引优化,库表结构优化 如何获取有性能问题的SQL 1.通过测试 ...
- 为什么 execute(`echo 中文`) 输出中文源码?
为什么 execute(echo 中文) 输出中文源码? import win.ui; /*DSG{{*/ var winform = win.form(text="管道演示";r ...
- App开发(连接外部服务器)
第一步:导入httpClient第二步: 容许网络接口权限<uses-permission android:name="android.permission.INTERNET" ...
- php魔术常量,_CLASS_,_METHOD_,_FUNCTION_
_CLASS_: 返回当前类的类名 _METHOD_:返回当前类方法的方法名(并显示类的调用,类名::方法名) _FUNCTION_:返回当前函数的函数名 _FILE_:当前文件的绝对路径(包含_FI ...
- ab工具压接口的时候post传参问题
ab -n 10000 -c 40 -p [参数所在文件] -T 'application/json' http://xxx 以上命令, 压测需要post json格式的参数的api时, 一定注 ...
- Block实现代理/通知效果
例子1:A控制器->跳转—>B控制器 , 假设想从B控制器回传数组给A控制器 实现:B控制器.h文件定义一个block参数,.m文件执行block,A控制器设置block内容 B.h文件/ ...
- 【转帖】虚拟化Pod性能比裸机还要好,原因竟然是这样!
虚拟化Pod性能比裸机还要好,原因竟然是这样! http://www.itpub.net/2020/02/27/5340/ 其实感觉 linux也可以做到 NUMA的节点优化 其实 直接在 ESXi上 ...
- 将hello程序作为驱动程序编译进系统内核
0x00开始 恩,可能是我比较愚钝,一个内核编译搞了一天,各种问题,各种bug,几度无奈,也是因为我突发奇想,并没有按照原来的那种操作,我直接把helloworld程序放到内核模块中编译成了一个驱动程 ...
- SeetaFaceEngine系列1:Face Detection编译和使用
SeetaFace,根据GitHub上的介绍,就是一个开源的人脸检测.矫正和识别的开源库,是采用C++来编写的,并且是在CPU上执行的,没有用到GPU,但是可以用SSE或者OpenMP来加速.整个库分 ...