golang struct 转map 及 map[string]*Struct 初始化和遍历
package main
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strconv"
"time"
)
type User struct {
a string
b string
}
type S struct {
User
Name string
Age int
Address string
}
//结构体转map方法1
func Struct2Map(obj interface{}) map[string]interface{} {
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
var data = make(map[string]interface{})
//func (v Value) NumField() int, 返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic
for i := 0; i < t.NumField(); i++ {
data[t.Field(i).Name] = v.Field(i).Interface()
}
return data
}
//结构体转map方法2
func StructToMapViaJson(data S) map[string]interface{} {
m := make(map[string]interface{})
//struct 转json
j, _ := json.Marshal(data)
//json 转map
json.Unmarshal(j, &m)
return m
}
func FillStruct(data map[string]interface{}, obj interface{}) error {
for k, v := range data {
//fmt.Println("k: ", k, " v: ", v)
err := SetField(obj, k, v)
if err != nil {
return err
}
}
return nil
}
func SetField(obj interface{}, k string, v interface{}) error {
//结构体属性值
structValue := reflect.ValueOf(obj).Elem()
//fmt.Println("structValue: ", structValue)
//结构体单个属性值
structFieldValue := structValue.FieldByName(k)
//fmt.Println("structFieldValue: ", structFieldValue)
if !structFieldValue.IsValid() {
return fmt.Errorf("No such field: %s in obj", k)
}
if !structFieldValue.CanSet() {
return fmt.Errorf("Cannot set %s field value", k)
}
//结构体属性类型
structFieldType := structFieldValue.Type()
val := reflect.ValueOf(v)
var err error
if structFieldType != val.Type() {
//类型转换
val, err = TypeConversion(fmt.Sprintf("%v", v), structFieldValue.Type().Name())
if err != nil {
return err
}
}
structFieldValue.Set(val)
return nil
}
func TypeConversion(value string, ntype string) (reflect.Value, error) {
fmt.Println("call TypeConversion...")
if ntype == "string" {
return reflect.ValueOf(value), nil
} else if ntype == "time.Time" {
t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
return reflect.ValueOf(t), err
} else if ntype == "Time" {
t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
return reflect.ValueOf(t), err
} else if ntype == "int" {
i, err := strconv.Atoi(value)
return reflect.ValueOf(i), err
} else if ntype == "int8" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(int8(i)), err
} else if ntype == "int32" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(int64(i)), err
} else if ntype == "int64" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(i), err
} else if ntype == "float32" {
i, err := strconv.ParseFloat(value, 64)
return reflect.ValueOf(float32(i)), err
} else if ntype == "float64" {
i, err := strconv.ParseFloat(value, 64)
return reflect.ValueOf(i), err
}
//else if .......增加其他一些类型的转换
return reflect.ValueOf(value), errors.New("未知的类型:" + ntype)
}
func main() {
var s S
Types := reflect.TypeOf(s)
//TypeData.FieldByIndex([]int{}) 返回 StructField
//[]int{}参数: 第一个是struct类型的索引(如果索引为参数一的数据类型不是struct会报错), 第二个是索引为参数一的结构体内属性的索引
//例如[]int{0,0} 会输出[0] a string,表示索引为0的结构体User内索引为0的数据是a
//[]int{0, 1} 会输出[1] b string
//[]int{1, 0}会报错, 因为索引为1的数据是S结构体中的数据 Name string,数据类型不是struct
res := Types.FieldByIndex([]int{0, 0})
fmt.Println("FieldByIndex: ", res.Index, res.Name, res.Type)
//struct to map
info := S{Name: "xsk", Age: 22, Address: "shanghai"}
data := Struct2Map(info)
fmt.Println("data: ", data, " ", "typeof(data): ", reflect.TypeOf(data))
for k, v := range data {
fmt.Println(k, v.(interface{}))
}
fmt.Println("---------")
data1 := StructToMapViaJson(info)
fmt.Println("data1: ", data1, " ", "typeof(data1): ", reflect.TypeOf(data1))
for k, v := range data1 {
fmt.Println(k, v.(interface{}))
}
fmt.Println("---------")
//map to struct
data2 := make(map[string]interface{})
data2["Name"] = "xsk"
data2["Age"] = 22
data2["Address"] = "shanghai"
result := &S{}
err := FillStruct(data2, result)
fmt.Println("err: ", err, " result: ", fmt.Sprintf("%+v", *result))
fmt.Println("---------")
//map[string]*Struct 下面几种初始化都行
//第一种
//var info1 = map[string]*S{"info": &S{Name: "mtt", Age: 23, Address: "shanghai"}}
//第二种
var info1 = map[string]*S{"info": &S{}, "other": &S{}}
info1["info"].Name = "mtt"
info1["info"].Age = 23
info1["info"].Address = "shanghai"
fmt.Println("info1: ", *info1["info"])
t := reflect.TypeOf(*info1["info"])
v := reflect.ValueOf(*info1["info"])
for k := 0; k < t.NumField(); k++ {
fmt.Printf("%s: %v\n", t.Field(k).Name, v.Field(k).Interface())
}
fmt.Println("---------")
//第三种
var info2 = map[string]*S{}
info2["info"] = &S{Name: "xly", Age: 1, Address: "shanghai"}
fmt.Println("info2: ", *info2["info"])
ty := reflect.TypeOf(*info2["info"])
vl := reflect.ValueOf(*info2["info"])
for k := 0; k < ty.NumField(); k++ {
fmt.Printf("%s: %v\n", ty.Field(k).Name, vl.Field(k).Interface())
}
}
golang 中 map 转 struct
package main
import (
"fmt"
"github.com/goinggo/mapstructure"
)
type Person struct {
Name string
Age int
}
func MapToStruct() {
mapInstance := make(map[string]interface{})
mapInstance["Name"] = "liang637210"
mapInstance["Age"] = 28
var person Person
//将 map 转换为指定的结构体
if err := mapstructure.Decode(mapInstance, &person); err != nil {
fmt.Println(err)
}
fmt.Printf("map2struct后得到的 struct 内容为:%v", person)
}
func main(){
MapToStruct()
}
golang struct 转map 及 map[string]*Struct 初始化和遍历的更多相关文章
- cannot assign to struct field xxx in map
golang 中对 map 类型中的 struct 赋值报错 type s struct{ name string age int}func main(){ a := map[string]s{ &q ...
- go 数组(array)、切片(slice)、map、结构体(struct)
一 数组(array) go语言中的数组是固定长度的.使用前必须指定数组长度. go语言中数组是值类型.如果将数组赋值给另一个数组或者方法中参数使用都是复制一份,方法中使用可以使用指针传递地址. 声明 ...
- Spark存储Parquet数据到Hive,对map、array、struct字段类型的处理
利用Spark往Hive中存储parquet数据,针对一些复杂数据类型如map.array.struct的处理遇到的问题? 为了更好的说明导致问题的原因.现象以及解决方案,首先看下述示例: -- 创建 ...
- GoLang基础数据类型--->字典(map)详解
GoLang基础数据类型--->字典(map)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 可能大家刚刚接触Golang的小伙伴都会跟我一样,这个map是干嘛的,是 ...
- Golang操作结构体、Map转化为JSON
结构体生成Json package main import ( "encoding/json" "fmt" ) type IT struct { Company ...
- Golang封装一个加锁的Map工具包
Golang封装一个加锁的Map工具包 直接上代码了,用的是读写锁,代码如下: package utils import ( "sync" ) type BeeMap struct ...
- sprinbcloud学习之-Failed to bind properties under 'logging.level' to java.util.Map<java.lang.String>
日志报错,提示Failed to bind properties under 'logging.level' to java.util.Map<java.lang.String>, 原因为 ...
- 原型模式 private static Map<String,Prototype> map = new HashMap<String,Prototype>();
public class PrototypeManager { /** * 用来记录原型的编号和原型实例的对应关系 */ private static Map<String,Prototype& ...
- Map 集合 和 String 字符串相互转换工具类
package com.skynet.rimp.common.utils.util; import java.util.Arrays; import java.util.HashMap; import ...
随机推荐
- luogu 4411 [BJWC2010]取数游戏 约数+dp
不大难的dp,暴力拆一下约数然后按照约数来统计即可. 注意:vector 很慢,所以一定特判一下,如果没有该数,就不要添加. Code: #include <bits/stdc++.h> ...
- OpenSSL 通过OCSP手动验证证书
翻译:https://raymii.org/s/articles/OpenSSL_Manually_Verify_a_certificate_against_an_OCSP.html?utm_sour ...
- hdu 5556 Land of Farms 最大团+暴力
Land of Farms Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tot ...
- 蓝桥 log大侠
标题:Log大侠 atm参加了速算训练班,经过刻苦修炼,对以2为底的对数算得飞快,人称Log大侠. 一天,Log大侠的好友 drd 有一些整数序列需要变换,Log大侠正好施展法力... 变换的规则是: ...
- SSO 断点登陆
1. 摘要 ( 注意:请仔细看下摘要,留心此文是否是您的菜,若浪费宝贵时间,深感歉意!!!) SSO这一概念由来已久,网络上对应不同场景的成熟SSO解决方案比比皆是,从简单到复杂,各式各样应有尽有!开 ...
- Linux命令行学习日志-ps ax
当我们需要查询某个运行中的进程的时候,这个命令就显得很有用了,可以查看当前进程的PID和状态(S代表睡眠,SW代表睡眠和等待,R表示运行中) ps ax //查看当前运行中的进程
- codeforces#1196F. K-th Path(最短路,思维题)
题目链接: https://codeforces.com/contest/1196/problem/F 题意: 在无向图的所有最短路点对中,求出第$k$大 数据范围: $ 1 \leq k \leq ...
- CF1204C
CF1204C-Anna, Svyatoslav and Maps 题意: 题目传送门 不想说了,阅读题. 解法: 先用floyd跑出各顶点间的最短路.把p(1)加入答案,然后沿着题目给的路径序列遍历 ...
- java线程基础方法详解
一.线程状态转换 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行 ...
- 【VMWare】虚拟机启动遇到黑屏,在命令行窗口输入netsh winsock reset并不管用 重新启动客户机就好了
现象:虚拟机启动后是莫名其妙的黑屏,而且它上面安装的MySql也无法访问了. 处置:上网百度方案,看到大多数网文推荐:“以管理员身份打开cmd,输入netsh winsock reset,然后重启机器 ...