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 ...
随机推荐
- eclipse上部署到tomcat不能自动部署maven管理的额jar包
- linux 安装禅道 和 CentOS 7 开放防火墙端口 命令
linux 安装禅道链接: https://www.cnblogs.com/maohuidong/p/9750202.html CentOS 7 开放防火墙端口 命令 链接:https://www. ...
- solr8.0.0基本安装和在springboot中的基本使用(win10)
1.下载solr 下载地址:http://archive.apache.org/dist/lucene/solr/ 该地址可以也可以下载以前的版本,我这边下载的solr-8.0.0.zip版本.下载完 ...
- Maven:Failure executing javac, but could not parse the error:javac: 无效的目标发行版: 1.8
eclipse中对着项目maven——>>maven install时出现错误:Failure executing javac, but could not parse the error ...
- 牛客——Rabbit的字符串
题目: 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 Rabbit得到了一个字符串,她的好朋 ...
- hook截获自定义消息
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- 查找ARP攻击源
问题: 内网有电脑中了ARP病毒,但是网络拓扑比较复杂.电脑数量较多,排查起来很困难.有什么方法可以找出ARP攻击源?[推荐3]排查方法: 1.使用Sniffer抓包.在网络内任意一台主机上运行抓包软 ...
- Leetcode第1题:两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的 两个 整数.你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元素.示例:给定 nums ...
- Vue.js——5.生命周期
Vue的生命周期 创建阶段new Vue1,beforeCreate() 表示在实例没有被创建出来之前会执行它加载data和methods2,caeated() data 和methods被初始化了 ...
- -mtime
大家在使用find命令中的mtime参数时候,会看到官方的解释如下: -mtime n File's data was last modified n*24 hours ...