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结构体值的交换的更多相关文章

  1. golang 结构体中的匿名接口

    golang 结构体中的匿名接口 代码示例 golang 中,可以给结构体增加匿名field,可参考 unknwon 大神的书. 匿名字段和内嵌结构体 但,golang同时也可以给结构体定义一个匿名i ...

  2. golang结构体json格式化的时间格式

    golang结构体json格式化的时间格式 在我们开发中,经常会解析time.Time 往往前台传过来的时候,是个string 但是我们希望在结构体转成time.Time type Param str ...

  3. GO开发[五]:golang结构体struct

    Go结构体struct Go语言的结构体(struct)和其他语言的类(class)有同等的地位,但Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性 ...

  4. golang结构体、接口、反射

    struct结构体 struct用来自定义复杂数据结构,可以包含多个字段属性,可以嵌套; go中的struct类型理解为类,可以定义方法,和函数定义有些许区别; struct类型是值类型. struc ...

  5. golang结构体

    声明结构体 定义结构体使用struct关键字.在结构体内部定义它们的成员变量和类型.如果成员变量的类型相同还可以把它们写到同一行. struct里面可以包含多个字段(属性) struct类型可以定义方 ...

  6. Golang结构体struct的使用(结构体嵌套, 匿名结构体等)

    转自: https://studygolang.com/articles/11313 golang中是没有class的,但是有一个结构体struct,有点类似,他没有像java,c++中继承的概念,但 ...

  7. 【转】golang 结构体和方法

    原文:https://www.jianshu.com/p/b6ae3f85c683 ---------------------------------------------------------- ...

  8. golang 结构体嵌入和匿名成员

    考虑一个二维的绘图程序,提供了一个各种图形的库,例如矩形.椭圆形.星形和轮形等几 何形状.这里是其中两个的定义 type Circle struct { X, Y, Radius int } type ...

  9. [Go] golang结构体成员与函数类型

    package main import ( "fmt" ) //定义一个类型 type tsh struct { //定义成员,类型是func() string test func ...

随机推荐

  1. eclipse上部署到tomcat不能自动部署maven管理的额jar包

  2. linux 安装禅道 和 CentOS 7 开放防火墙端口 命令

    linux 安装禅道链接:  https://www.cnblogs.com/maohuidong/p/9750202.html CentOS 7 开放防火墙端口 命令 链接:https://www. ...

  3. solr8.0.0基本安装和在springboot中的基本使用(win10)

    1.下载solr 下载地址:http://archive.apache.org/dist/lucene/solr/ 该地址可以也可以下载以前的版本,我这边下载的solr-8.0.0.zip版本.下载完 ...

  4. 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 ...

  5. 牛客——Rabbit的字符串

    题目: 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 Rabbit得到了一个字符串,她的好朋 ...

  6. hook截获自定义消息

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  7. 查找ARP攻击源

    问题: 内网有电脑中了ARP病毒,但是网络拓扑比较复杂.电脑数量较多,排查起来很困难.有什么方法可以找出ARP攻击源?[推荐3]排查方法: 1.使用Sniffer抓包.在网络内任意一台主机上运行抓包软 ...

  8. Leetcode第1题:两数之和

    给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的 两个 整数.你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元素.示例:给定 nums ...

  9. Vue.js——5.生命周期

    Vue的生命周期 创建阶段new Vue1,beforeCreate() 表示在实例没有被创建出来之前会执行它加载data和methods2,caeated() data 和methods被初始化了 ...

  10. -mtime

    大家在使用find命令中的mtime参数时候,会看到官方的解释如下:  -mtime n               File's data was last modified n*24 hours ...