Golang实现优雅的将struct转换为map

目录
  • 前言
  • 方式1:使用JSON序列和反序列化
  • 方式2:使用反射
  • 两种方式对比
  • 封装到工具包

前言

在项目实践中,有时候我们需要将struct结构体转为map映射表,然后基于map做数据裁剪或操作。那么下面我来介绍下常用的两种转换方式,以及对它们做对比,最后采用更优雅的方式,封装到我们的项目工程的工具包里

方式1:使用JSON序列和反序列化

使用json操作的这个方式是比较简单的,容易想到也易实现。直接上代码:

package main

import (
    "encoding/json"
    "fmt"
    "time"
)

type Person struct {
    Name    string `json:"name"`
    Address string `json:"address"`
}

func main() {
    t := time.Now().UnixNano()
    m := make(map[string]interface{})
    person := Person{
       Name:    "zhangsan",
       Address: "北京海淀",
    }
    j, _ := json.Marshal(person)
    json.Unmarshal(j, &m)
    fmt.Println(m)
    fmt.Println(fmt.Sprintf("JSON-duration:%d", time.Now().UnixNano() - t))
}

输出结果:

map[address:北京海淀 name:zhangsan]

JSON-duration:174000

方式2:使用反射

通过反射机制,灵活的做类型转换。具体实现:

package main

import (
    "fmt"
    "reflect"
    "time"
)

type Person struct {
    Name    string `json:"name"`
    Address string `json:"address"`
}

func main() {
    t := time.Now().UnixNano()
    m := make(map[string]interface{})
    person := Person{
        Name:    "zhangsan",
        Address: "北京海淀",
    }

    elem := reflect.ValueOf(&person).Elem()
    relType := elem.Type()
    for i := 0; i < relType.NumField(); i++ {
        name := relType.Field(i).Name
        m[name] = elem.Field(i).Interface()
    }

    fmt.Println(m)
    fmt.Println(fmt.Sprintf("反射-duration:%d", time.Now().UnixNano() - t))
}

输出结果:

map[Address:北京海淀 Name:zhangsan]

反射-duration:60000

两种方式对比

执行效率:

使用反射的效率,明显比使用json的效率要高,接近3倍

输出结果:

使用json能达到预期,正常解析出结构体tag;

使用反射未能达到预期,未解析出结构体tag,字段是以结构体定义为准

封装到工具包

基于上面两种方式的对比,我们决定采用反射机制,并对结构体tag解析做兼容,优雅的将struct转换为map,并封装到工具包中

具体实现,工具包代码:

package utils

import (
    "reflect"
    "strings"
)

type IStruct interface {
    GetStructData() interface{}
}

//struct转map
//使用反射实现,完美地兼容了json标签的处理
func StructToMap(st IStruct) map[string]interface{} {
    m := make(map[string]interface{})
    in := st.GetStructData()
    val := reflect.ValueOf(in)
    if val.Kind() == reflect.Ptr {
        val = val.Elem()
    }
    if val.Kind() != reflect.Struct {
        return m
    }

    relType := val.Type()
    for i := 0; i < relType.NumField(); i++ {
        name := relType.Field(i).Name
        tag := relType.Field(i).Tag.Get("json")
        if tag != "" {
            index := strings.Index(tag, ",")
            if index == -1 {
                name = tag
            } else {
                name = tag[:index]
            }
        }
        m[name] = val.Field(i).Interface()
    }
    return m
}

测试代码:

package main

import (
    "fmt"
    "learn-go/utils"
    "time"
)

type Person struct {
    Name    string `json:"name"`
    Address string `json:"address"`
}

//注意:必须实现这个方法,才能正确调用工具包转换方法
func (p Person) GetStructData() interface{} {
    return p
}

func main() {
    t := time.Now().UnixNano()
    m := make(map[string]interface{})
    person := Person{
        Name:    "zhangsan",
        Address: "北京海淀",
    }

    m = utils.StructToMap(person)
    fmt.Println(m)
    fmt.Println(fmt.Sprintf("反射2-duration:%d", time.Now().UnixNano() - t))
}

输出结果:

map[address:北京海淀 name:zhangsan]

反射2-duration:65000

结论:

执行效率高的同时,输出结果也符合预期,能正确的解析出结构体tag

到此这篇关于Golang实现优雅的将struct转换为map的文章就介绍到这了,更多相关Golang struct转map内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang struct, map, json之间的相互转换

    本文用于记录我在 golang 学习阶段遇到的类型转换问题,针对的是 json .map.struct 之间相互转换的问题,用到的技术 json .mapstructure.reflect 三个类库 公共代码区域 package main import ( "encoding/json" "fmt" "testing" ) type UserInfoVo struct { Id string `json:"id"` UserN

  • 详解Go开发Struct转换成map两种方式比较

    最近做Go开发的时候接触到了一个新的orm第三方框架gorose,在使用的过程中,发现没有类似beego进行直接对struct结构进行操作的方法,有部分API是通过map进行数据库相关操作,那么就需要我们把struct转化成map,下面是是我尝试两种不同struct转换成map的方法 mport ( "encoding/json" "fmt" "reflect" "time" ) type Persion struct { I

  • golang 实现struct、json、map互相转化

    一.Json和struct互换 (1)Json转struct例子: package main import ( "fmt" "encoding/json" ) type People struct { Name string `json:"name_title"` Age int `json:"age_size"` } func JsonToStructDemo(){ jsonStr := ` { "name_tit

  • Golang实现优雅的将struct转换为map

    目录 前言 方式1:使用JSON序列和反序列化 方式2:使用反射 两种方式对比 封装到工具包 前言 在项目实践中,有时候我们需要将struct结构体转为map映射表,然后基于map做数据裁剪或操作.那么下面我来介绍下常用的两种转换方式,以及对它们做对比,最后采用更优雅的方式,封装到我们的项目工程的工具包里 方式1:使用JSON序列和反序列化 使用json操作的这个方式是比较简单的,容易想到也易实现.直接上代码: package main import ( "encoding/json"

  • Golang判断struct/slice/map是否相等以及对比的方法总结

    目录 前言 == 的对比方式 == 适用的类型 slice和map使用 == channel使用 == struct结构体使用== reflect.DeepEqual() 和cmp.Equal() reflect.DeepEqual() cmp.Equal() cmp和DeepEqual的区别 性能比较 总结 前言 平时开发中对比两个struct或者map.slice是否相等是经常遇到的,有很多对比的方式,比如==,reflect.DeepEqual(),cmp.Equal()等也是经常容易混淆

  • golang如何优雅的编写事务代码示例

    前言 新手程序员大概有如下特点 if嵌套经常超过3层.经常出现重复代码.单个函数代码特别长. 只会crud,对语言特性和语言的边界不了解. 不懂面向对象原则和设计模式,以为copy代码就算学会了,常见的是代码职责不明确或者写出万能类 不知道数据结构和算法的重要性,以为靠硬件能解决运行慢的问题 架构不懂,搭建框架不会,搭建环境不会,使用的软件底层原理一问三不知 其实吧,很多人干了很多年,看似是老手,平时工作看似很忙,其实做的都是最简单的活. 这就像去锻炼,有的人每天练的很积极,准时打卡,频繁发朋友

  • 详解Golang如何优雅的终止一个服务

    目录 前言 1 Shutdown 方法 2 signal.Notify 函数 3 Server 优雅的终止 总结 前言 采用常规方式启动一个 Golang http 服务时,若服务被意外终止或中断,即未等待服务对现有请求连接处理并正常返回且亦未对服务停止前作一些必要的处理工作,这样即会造成服务硬终止.这种方式不是很优雅. 参看如下代码,该 http 服务请求路径为根路径,请求该路径,其会在 2s 后返回 hello. var addr = flag.String("server addr&quo

  • java 三种将list转换为map的方法详解

    java 三种将list转换为map的方法详解 在本文中,介绍三种将list转换为map的方法: 1) 传统方法 假设有某个类如下 class Movie { private Integer rank; private String description; public Movie(Integer rank, String description) { super(); this.rank = rank; this.description = description; } public Int

  • 在Java 8中将List转换为Map对象方法

    假设有一个员工对象: <b>public</b> <b>class</b> Employee { <font><i>// member variables</i></font><font> <b>private</b> <b>int</b> empId; <b>private</b> String empName; <b&

  • Java将json对象转换为map键值对案例详解

    本文的目的是把json串转成map键值对存储,而且只存储叶节点的数据 比如json数据如下: {responseHeader:{status:0,QTime:0},spellcheck:{suggestions:{中国:{numFound:9,startOffset:0,endOffset:2,suggestion:[中国工商银行, 中国人民, 中国国际, 中国农业, 中国市场, 中国经济, 中国人, 中国广播, 中国文化]}},collations:{collation:中国工商银行}}} 如

  • 使用golang如何优雅的关机或重启操作示例

    目录 前言 优雅地关机 什么是优雅关机? 如何实现优雅关机? 优雅地重启 总结 前言 我们编写的Web项目部署之后,经常会因为需要进行配置变更或功能迭代而重启服务,单纯的kill -9 pid的方式会强制关闭进程,这样就会导致服务端当前正在处理的请求失败,那有没有更优雅的方式来实现关机或重启呢? 阅读本文需要了解一些UNIX系统中信号的概念,请提前查阅资料预习. 优雅地关机 什么是优雅关机? 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种

  • springboot加载一个properties文件转换为map方式

    目录 加载一个properties文件转换为map 1.创建一个properties文件 2.在java中将该properties文件转换为map properties配置文件出现乱码 加载一个properties文件转换为map springboot中比较常见的获取properties中的值,就是直接在字段上面添加@Value的属性. 但有时候我们不确定key有多少,但是会有一定的规律(这个规律是根据业务来定的,如下),这时候我们就可以考虑将properties中的信息转换为一个map,然后根

  • Java三种方法将List转换为Map的实例

    1.for循环 import com.google.common.base.Function; import com.google.common.collect.Maps; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ListToMap { public static void main(String[] args)

随机推荐