dongyan1974 2017-07-22 12:47
浏览 40
已采纳

合并两个不同类型的相似结构

I have the following structs...

type Menu struct {
    Id          string     `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
    Name        string     `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
    Description string     `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"`
    Mixers      []*Mixer   `protobuf:"bytes,4,rep,name=mixers" json:"mixers,omitempty"`
    Sections    []*Section `protobuf:"bytes,5,rep,name=sections" json:"sections,omitempty"`
}

And...

type Menu struct {
    ID          bson.ObjectId `json:"id" bson:"_id"`
    Name        string        `json:"name" bson:"name"`
    Description string        `json:"description" bson:"description"`
    Mixers      []Mixer       `json:"mixers" bson:"mixers"`
    Sections    []Section     `json:"sections" bson:"sections"`
}

I basically need to convert between the two struct types, I've attempted to use mergo, but that can only merge structs that are assignable to one another. The only solution I have so far is iterating through each struct, converting the ID by re-assigning it and converting its type between string and bson.ObjectId. Then iterating through each map field and doing the same. Which feels like an inefficient solution.

So I'm attempting to use reflection to be more generic in converting between the two ID's. But I can't figure out how I can effectively merge all of the other fields that do match automatically, so I can just worry about converting between the ID types.

Here's the code I have so far...

package main

import (
    "fmt"
    "reflect"

    "gopkg.in/mgo.v2/bson"
)

type Sub struct {
    Id bson.ObjectId
}

type PbSub struct {
    Id string
}

type PbMenu struct {
    Id   string
    Subs []PbSub
}

type Menu struct {
    Id   bson.ObjectId
    Subs []Sub
}

func main() {
    pbMenus := []*PbMenu{
        &PbMenu{"1", []PbSub{PbSub{"1"}}},
        &PbMenu{"2", []PbSub{PbSub{"1"}}},
        &PbMenu{"3", []PbSub{PbSub{"1"}}},
    }

    newMenus := Serialise(pbMenus)
    fmt.Println(newMenus)
}

type union struct {
    PbMenu
    Menu
}

func Serialise(menus []*PbMenu) []Menu {
    newMenus := []Menu{}
    for _, v := range menus {
        m := reflect.TypeOf(*v)
        fmt.Println(m)
        length := m.NumField()
        for i := 0; i < length; i++ {
            field := reflect.TypeOf(v).Field(i)
            fmt.Println(field.Type.Kind())
            if field.Type.Kind() == reflect.Map {
                fmt.Println("is map")
            }
            if field.Name == "Id" && field.Type.String() == "string" {

                // Convert ID type
                id := bson.ObjectId(v.Id)
                var dst Menu
                dst.Id = id

                // Need to merge other matching struct fields

                newMenus = append(newMenus, dst)
            }
        }
    }
    return newMenus
}

I'm can't just manually re-assign the fields because I'm hoping to detect maps on the structs fields and recursively perform this function on them, but the fields won't be the same on embedded structs.

Hope this makes sense!

  • 写回答

1条回答 默认 最新

  • dongtuo8170 2017-07-22 20:16
    关注

    I think that it is probably better to write your own converter, because you will always have some cases that are not covered by existing libs\tools for that.

    My initial implementation of it would be something like this: basic impl of structs merger

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog