英文:
Golang return child struct in place of parent like in c++
问题
我正在尝试编写一个通用函数,可以返回多个不同的子对象。目标是能够将它们作为请求 JSON 主体返回。
代码如下:
type GenericType struct {
V1 string `json:"v1"`
V2 string `json:"v2"`
}
type SubType struct {
GenericType
V3 string `json:"v3"`
}
func TestFunc() GenericType {
val := SubType{
GenericType: GenericType{
V1: "a",
V2: "b",
},
V3: "c",
}
return val
}
错误信息为:
无法将 val(类型为 SubType)作为返回参数中的 GenericType 类型使用
是否可能在父指针中返回一个子结构体,而不丢失该子结构体的字段,并将其作为 JSON 对象返回到响应主体中?
英文:
I am trying to have a generic function that can return various multiple child objects. The idea is to be able to return those in a request json body.
The code is as follows
GenericType struct {
V1 string `json:"v1"`
V2 string `json:"v2"`
}
SubType struct {
GenericType
V3 string `json:"v3"`
}
func TestFunc() GenericType {
val := SubType{
GenericType: GenericType{
V1: "a",
V2: "b",
},
V3: "c",
}
return val
}
The error is
cannot use val (type SubType) as type GenericType in return argument
Is it possible to return a descendant struct in a parent pointer without losing the fields of that descendant struct and then return it as a JSON object in response body?
答案1
得分: 3
你不能将嵌入作为继承的替代品,但你可以使用接口来实现类似的功能。代码示例如下:
type Generic interface {
V1() string
V2() string
}
type parent struct {
// ...
}
type child struct {
// ...
}
// parent
func (p *parent) V1() string {
return "parent V1"
}
func (p *parent) V2() string {
return "parent V2"
}
// child
func (c *child) V1() string {
return "child V1"
}
func (c *child) V2() string {
return "child V2"
}
// 进一步的子类方法
func NewGeneric() Generic {
return &parent{}
// 或者
// return &child{}
}
以上代码示例中,Generic
是一个接口,定义了 V1()
和 V2()
两个方法。parent
和 child
分别实现了这个接口。你可以根据需要选择返回 parent
或者 child
的实例作为 NewGeneric()
的结果。
英文:
You can't use embedding as a substitute for inheritance. You could use interfaces for that though. Something like:
type Generic interface {
V1() string
V2() string
}
type parent struct {
// ...
}
type child struct {
// ...
}
// parent
func (p *parent) V1() string {
return "parent V1"
}
func (p *parent) V2() string {
return "parent V2"
}
// child
func (c *child) V1() string {
return "child V1"
}
func (c *child) V2() string {
return "child V2"
}
// further child methods
func NewGeneric() Generic {
return &parent{}
// or
// return &child{}
}
答案2
得分: 1
Go语言没有继承(像C++或Java那样),只有组合和接口。所以你的函数只能返回一个类型的结构体(或指针)或接口。初步可以认为接口与C++中的纯虚类几乎相同。
在你的情况下,接口更好。现在取决于程序的其余部分如何处理返回值。如果需要调用几个方法(在Go语言中,我们更喜欢只有几个方法的接口,最理想的情况是只有一个方法)。
例如:
type GenericType interface {
getV1() string
getV2() string
}
但不幸的是,对于所有可以序列化为JSON的对象,我们没有任何公共方法(例如int、string或数组),因此我们必须使用没有公共方法的接口 - interface{}。
英文:
Go does not have inheritance (like C++ or Java), but only composition and interfaces. So your function could return only one type structure (or pointer) or interface. As a first approximation you could think that interface is nearly the same as pure abstract class in C++).
In your case interface is better. And now it depends how rest of the program will work with returned value. If it need to call a few methods (in go we prefer interface with only few method - ideal is one).
Eg.
type GenericType interface {
getV1() string
getV2() string
}
But unfortunately - for all object that could be serialized into JSON we don't have any common method (eg. int, string or arrays), therefore we have to use interface with no common method - interface{}.
答案3
得分: 0
嵌入
在Go语言中,嵌入(embedding)不允许继承属性(因为它不是继承)。当你将一个结构体嵌入到另一个结构体中时,你是将其方法(而不是属性)组合到一个新的组合中。
> Go语言没有提供典型的、基于类型的子类化概念,但它确实可以通过在结构体或接口中嵌入类型来“借用”实现的一部分。
接口
Go语言提供了接口来实现泛型类型,并提供类型断言来访问具体类型及其属性。
type generic interface {
say() string
}
type type1 struct {
msg string
}
func (t type1) say() string {
return t.msg
}
type type2 struct{}
func (t type2) say() string {
return "I'm type 2"
}
func main() {
t1 := type1{"Hey! I'm type1"}
t2 := type2{}
tl := []generic{t1, t2}
for _, i := range tl {
switch v := i.(type) {
case type1:
fmt.Println(v.say())
fmt.Println(v.msg)
case type2:
fmt.Println(v.say())
// fmt.Println(v.msg) Uncomment to see that type2 has no msg attribute.
}
}
}
英文:
Embedding
Embedding in Go doesn't allow to inherit (since it is not inheritance) attributes. When you are embedding one struct to another you are composing its' methods (not attributes) to a new composition.
> Go does not provide the typical, type-driven notion of subclassing, but it does have the ability to “borrow” pieces of an implementation by embedding types within a struct or interface.
Interfaces
Go provides <strike>awesome</strike> interfaces to implement generic types and type assertion to have access to concrete types and its' attributes.
type generic interface {
say() string
}
type type1 struct {
msg string
}
func (t type1) say() string {
return t.msg
}
type type2 struct{}
func (t type2) say() string {
return "I'm type 2"
}
func main() {
t1 := type1{"Hey! I'm type1"}
t2 := type2{}
tl := []generic{t1, t2}
for _, i := range tl {
switch v := i.(type) {
case type1:
fmt.Println(v.say())
fmt.Println(v.msg)
case type2:
fmt.Println(v.say())
// fmt.Println(v.msg) Uncomment to see that type2 has no msg attribute.
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论