doz95923 2018-05-10 09:10
浏览 68
已采纳

如何复制结构和取消引用所有指针

How do you copy the Item struct and all pointers to a new struct?

type Item struct {
    A    []*ASet     `json:"a,omitempty"`
    B    []*BSet.    `json:"b,omitempty"`
    C    []*CSet.    `json:"c,omitempty"`
}


type ASet struct {
    UID   string     `json:"uid,omitempty"`
    Items []*ItemA `json:"member,omitempty"`
}

type ItemA struct {
    UID  string `json:"uid,omitempty"`
    Portset []*PortSet `json:"portset,omitempty"`
}

type PortSet struct {
    UID   string     `json:"uid,omitempty"`
    Ports []*Port `json:"member,omitempty"`
}

type Port struct {
    UID  string `json:"uid,omitempty"`
    Port int    `json:"port,omitempty"`
}

I don't want the new struct to reference the old struct.

  • 写回答

1条回答 默认 最新

  • doushi3803 2018-05-10 09:19
    关注

    What you want is essentially a deep copy which is not supported by the standard library.

    Your choices:

    • Do the copy "manually", e.g. create a new struct and copy the fields, where pointers or slices/maps/channels/etc must be duplicated manually, in a recursive manner.
      This is easiest done by assigning your struct to another one which copies all fields, so you essentially only need to nurture pointers/maps/slices etc. (but recursively).
    • Use an external library, e.g. github.com/mohae/deepcopy, github.com/ulule/deepcopier or github.com/mitchellh/copystructure
    • Marshal your struct to some format (e.g. JSON), then unmarshal into another variable.

    The last option could look like this:

    var i1 Item
    data, err := json.Marshal(i1)
    if err != nil {
        panic(err)
    }
    
    var i2 Item
    if err := json.Unmarshal(data, &i2); err != nil {
        panic(err)
    }
    // i2 holds a deep copy of i1
    

    Note that marshaling/unmarshaling isn't particularly efficient, but easy and compact. Also note that this might not handle recursive data structures well, might even hang or panic (e.g. a field points to the containing struct), but handling recursive structures may be a problem to all solutions. Also note that this won't clone unexported fields.

    The good thing about this marshaling / unmarshaling is that you can easily create a helper function to deep-copy "any" values:

    func deepCopy(v interface{}) (interface{}, error) {
        data, err := json.Marshal(v)
        if err != nil {
            return nil, err
        }
    
        vptr := reflect.New(reflect.TypeOf(v))
        err = json.Unmarshal(data, vptr.Interface())
        if err != nil {
            return nil, err
        }
        return vptr.Elem().Interface(), err
    }
    

    Testing it:

    p1 := image.Point{X: 1, Y: 2}
    fmt.Printf("p1 %T %+v
    ", p1, p1)
    
    p2, err := deepCopy(p1)
    if err != nil {
        panic(err)
    }
    
    p1.X = 11
    fmt.Printf("p1 %T %+v
    ", p1, p1)
    fmt.Printf("p2 %T %+v
    ", p2, p2)
    

    Output (try it on the Go Playground):

    p1 image.Point (1,2)
    p1 image.Point (11,2)
    p2 image.Point (1,2)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用ns3仿真出5G核心网网元
  • ¥15 matlab答疑 关于海上风电的爬坡事件检测
  • ¥88 python部署量化回测异常问题
  • ¥30 酬劳2w元求合作写文章
  • ¥15 在现有系统基础上增加功能
  • ¥15 远程桌面文档内容复制粘贴,格式会变化
  • ¥15 关于#java#的问题:找一份能快速看完mooc视频的代码
  • ¥15 这种微信登录授权 谁可以做啊
  • ¥15 请问我该如何添加自己的数据去运行蚁群算法代码
  • ¥20 用HslCommunication 连接欧姆龙 plc有时会连接失败。报异常为“未知错误”