如何将结构转换为具有更少字段的不同结构

问题描述 投票:0回答:5

我正在尝试将 Big 类型的结构复制到 Small 类型,而不显式创建具有相同字段的 Small 类型的新结构。

我尝试过搜索其他类似的问题,例如 thisthis,但不同结构类型之间的所有转换仅在结构具有相同字段时才会发生。

这是我尝试做的一个例子:

// Big has all the fields that Small has including some new ones.
type Big struct {
    A int
    B string
    C float
    D byte
}

type Small struct {
    A int
    B string
}

// This is the current solution which I hope to not use.
func ConvertFromBigToSmall(big Big) Small {
    return Small{
        A: big.A,
        B: big.B,
    }
}

我期望能够做这样的事情,但它不起作用:

big := Big{}
small := Small(big)

有没有一种方法可以在不使用

Big
函数的情况下在
Small
Convert
之间进行转换(甚至反之亦然)?

go struct
5个回答
12
投票

对此没有内置支持。如果您确实需要这个,您可以编写一个使用反射来复制字段的通用函数。

或者你可以重新设计。如果

Big
Small
加上一些其他附加字段,为什么不在
Small
中重用
Big

type Small struct {
    A int
    B string
}

type Big struct {
    S Small
    C float
    D byte
}

那么如果你有一个

Big
结构体,那么你也有一个
Small
Big.S
。如果您有
Small
并且需要
Big
Big{S: small}

如果您担心失去较短字段名称的便利性或不同的编组结果,请使用嵌入而不是命名字段:

type Big struct {
    Small // Embedding
    C float
    D byte
}

那么这些也是有效的:

Big.A
Big.B
。但如果您需要
Small
值,您可以使用非限定类型名称作为字段名称来引用嵌入字段,例如
Big.Small
(请参阅Golang 嵌入式结构类型)。同样,要从
Big
创建
Small
Big{Small: small}


2
投票

有没有一种方法可以在不使用

Big
函数的情况下在
Small
Convert
之间进行转换(甚至反之亦然)?

唯一的选择是手动执行此操作,就像您所做的那样。无论您是否将其包装在函数中,都是品味/环境的问题。


2
投票

你可以这样做:

package main

import (
    "fmt"
)

type Big struct {
    Small
    C float32
    D byte
}

type Small struct {
    A int
    B string
}

func main() {
    big := new(Big)
    big.A = 1
    big.B = "test"
    big.C = 2.3
    fmt.Printf("big struct: %+v", big)
    fmt.Println()
    small := big.Small
    fmt.Printf("small struct: %+v", small)
    fmt.Println()
}

输出:

big struct: &{Small:{A:1 B:test} C:2.3 D:0}
small struct: {A:1 B:test}

游乐场链接:https://play.golang.org/p/-jP8Wb--att


1
投票

恐怕没有直接的方法可以做到这一点。你所做的是正确的方法。

您可以尝试将第一个对象写入 JSON,然后尝试将其解析回第二个对象。不过,我不会走这条路。

还有一种方式,也是比较具体的一种方式,就是Big对象会继承Small对象。那么你就可以垂头丧气了。再说一遍,我不会那样做,但如果你必须这样做......


0
投票

我在我的项目中使用这个:

func MarshalFrom(source any, destination any) error {
    bytes, err := json.Marshal(source)
    json.Unmarshal(bytes, destination)
    return err
}

所以你可以轻松地说

var small = &Small{};
MarshalFrom(&big, small)
fmt.printf("small : %v", small)
© www.soinside.com 2019 - 2024. All rights reserved.