我正在尝试将 Big 类型的结构复制到 Small 类型,而不显式创建具有相同字段的 Small 类型的新结构。
我尝试过搜索其他类似的问题,例如 this 和 this,但不同结构类型之间的所有转换仅在结构具有相同字段时才会发生。
这是我尝试做的一个例子:
// 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
之间进行转换(甚至反之亦然)?
对此没有内置支持。如果您确实需要这个,您可以编写一个使用反射来复制字段的通用函数。
或者你可以重新设计。如果
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}
。
有没有一种方法可以在不使用
函数的情况下在Big
到Small
之间进行转换(甚至反之亦然)?Convert
唯一的选择是手动执行此操作,就像您所做的那样。无论您是否将其包装在函数中,都是品味/环境的问题。
你可以这样做:
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}
恐怕没有直接的方法可以做到这一点。你所做的是正确的方法。
您可以尝试将第一个对象写入 JSON,然后尝试将其解析回第二个对象。不过,我不会走这条路。
还有一种方式,也是比较具体的一种方式,就是Big对象会继承Small对象。那么你就可以垂头丧气了。再说一遍,我不会那样做,但如果你必须这样做......
我在我的项目中使用这个:
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)