Go-复制结构之间的所有常用字段 [英] Go- Copy all common fields between structs

查看:119
本文介绍了Go-复制结构之间的所有常用字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个存储JSON的数据库,以及一个通过HTTP post提供外部API的服务器,可以更改此数据库中的值。数据库在内部由不同的流程使用,因此有一个通用的命名方案。



客户看到的密钥是不同的,但映射1:1与键数据库(有未暴露的键)。例如:

这是在数据库中:

  { bit_size:8,secret_key:false} 

然后提交给客户端: p>

  {num_bits:8} 

API可以根据字段名称进行更改,但数据库始终具有一致的键。



我已经在结构,带有不同的标志到JSON编码器:

  type DB结构{
NumBits int`json:bit_size `
Secret bool`json:secret_key`
}
类型用户结构{
NumBits int`json:num_bits`
}

我使用编码/ json 来执行Marshal / Unmarshal 。



反映这是正确的工具吗?有没有更简单的方法,因为所有的键都是一样的?我正在考虑一些 memcpy (如果我保持用户字段的顺序相同)。

解决方案

这是一个使用反射的解决方案。如果您需要更复杂的嵌入式结构字段等结构,您必须进一步开发它。



http://play.golang.org/p/iTaDgsdSaI

 包$ 
$ b导入(
编码/ json
fmt
反映


类型M map [string] interface {} //只是一个别名

var Record = [] byte(`{bit_size:8,secret_key:false}`)

类型DB结构{
NumBits int`json:bit_size`
秘密布尔`json:secret_key`
}

类型用户结构{
NumBits int`json:num_bits`
}

func main(){
d:= new(DB)
e:= json.Unmarshal ,d)如果e!= nil {
panic(e)
}
m:= mapFields(d)
fmt.Println(Mapped fields:, m)
u:= new(User)
o:= applyMap(u,m)
fmt.Println(Applied map:,o)
j,e:= js on.Marshal(o)
if e!= nil {
panic(e)
}
fmt.Println(Output JSON:,string(j))

$ b $ func applyMap(u * User,m M)M {
t:= reflect.TypeOf(u).Elem()
o:= make(M)
for i:= 0;我< t.NumField(); i ++ {
f:= t.FieldByIndex([] int {i})
//跳过未导出的字段
if f.PkgPath!={
continue
}
if x,ok:= m [f.Name]; OK {
k:= f.Tag.Get(json)
o [k] = x
}
}
return
}
$ b $ func mapFields(x * DB)M {
o:= make(M)
v:= reflect.ValueOf(x).Elem()
t:= v.Type ()
for i:= 0;我< v.NumField(); i ++ {
f:= t.FieldByIndex([] int {i})
//跳过未导出的字段
if f.PkgPath!={
continue
}
o [f.Name] = v.FieldByIndex([] int {i}).interface()
}
return o
}


I have a database that stores JSON, and a server that provides an external API to whereby through an HTTP post, values in this database can be changed. The database is used by different processes internally, and as such have a common naming scheme.

The keys the customer sees are different, but map 1:1 with the keys in the database (there are unexposed keys). For example:

This is in the database:

{ "bit_size": 8, "secret_key": false }

And this is presented to the client:

{ "num_bits": 8 }

The API can change with respect to field names, but the database always has consistent keys.

I have named the fields the same in the struct, with different flags to the json encoder:

type DB struct {
    NumBits int  `json:"bit_size"`
    Secret  bool `json:"secret_key"`
}
type User struct {
    NumBits int `json:"num_bits"`
}

I'm using encoding/json to do the Marshal/Unmarshal.

Is reflect the right tool for this? Is there an easier way since all of the keys are the same? I was thinking some kind of memcpy (if I kept the user fields in the same order).

解决方案

Here's a solution using reflection. You have to further develop it if you need more complex structures with embedded struct fields and such.

http://play.golang.org/p/iTaDgsdSaI

package main

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

type M map[string]interface{} // just an alias

var Record = []byte(`{ "bit_size": 8, "secret_key": false }`)

type DB struct {
    NumBits int  `json:"bit_size"`
    Secret  bool `json:"secret_key"`
}

type User struct {
    NumBits int `json:"num_bits"`
}

func main() {
    d := new(DB)
    e := json.Unmarshal(Record, d)
    if e != nil {
        panic(e)
    }
    m := mapFields(d)
    fmt.Println("Mapped fields: ", m)
    u := new(User)
    o := applyMap(u, m)
    fmt.Println("Applied map: ", o)
    j, e := json.Marshal(o)
    if e != nil {
        panic(e)
    }
    fmt.Println("Output JSON: ", string(j))
}

func applyMap(u *User, m M) M {
    t := reflect.TypeOf(u).Elem()
    o := make(M)
    for i := 0; i < t.NumField(); i++ {
        f := t.FieldByIndex([]int{i})
        // skip unexported fields
        if f.PkgPath != "" {
            continue
        }
        if x, ok := m[f.Name]; ok {
            k := f.Tag.Get("json")
            o[k] = x
        }
    }
    return o
}

func mapFields(x *DB) M {
    o := make(M)
    v := reflect.ValueOf(x).Elem()
    t := v.Type()
    for i := 0; i < v.NumField(); i++ {
        f := t.FieldByIndex([]int{i})
        // skip unexported fields
        if f.PkgPath != "" {
            continue
        }
        o[f.Name] = v.FieldByIndex([]int{i}).Interface()
    }
    return o
}

这篇关于Go-复制结构之间的所有常用字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆