在Golang中,可以像C++一样返回子结构体代替父结构体。

huangapple go评论115阅读模式
英文:

Golang return child struct in place of parent like in c++

问题

我正在尝试编写一个通用函数,可以返回多个不同的子对象。目标是能够将它们作为请求 JSON 主体返回。

代码如下:

  1. type GenericType struct {
  2. V1 string `json:"v1"`
  3. V2 string `json:"v2"`
  4. }
  5. type SubType struct {
  6. GenericType
  7. V3 string `json:"v3"`
  8. }
  9. func TestFunc() GenericType {
  10. val := SubType{
  11. GenericType: GenericType{
  12. V1: "a",
  13. V2: "b",
  14. },
  15. V3: "c",
  16. }
  17. return val
  18. }

错误信息为:

  1. 无法将 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

  1. GenericType struct {
  2. V1 string `json:"v1"`
  3. V2 string `json:"v2"`
  4. }
  5. SubType struct {
  6. GenericType
  7. V3 string `json:"v3"`
  8. }
  9. func TestFunc() GenericType {
  10. val := SubType{
  11. GenericType: GenericType{
  12. V1: "a",
  13. V2: "b",
  14. },
  15. V3: "c",
  16. }
  17. return val
  18. }

The error is

  1. 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

你不能将嵌入作为继承的替代品,但你可以使用接口来实现类似的功能。代码示例如下:

  1. type Generic interface {
  2. V1() string
  3. V2() string
  4. }
  5. type parent struct {
  6. // ...
  7. }
  8. type child struct {
  9. // ...
  10. }
  11. // parent
  12. func (p *parent) V1() string {
  13. return "parent V1"
  14. }
  15. func (p *parent) V2() string {
  16. return "parent V2"
  17. }
  18. // child
  19. func (c *child) V1() string {
  20. return "child V1"
  21. }
  22. func (c *child) V2() string {
  23. return "child V2"
  24. }
  25. // 进一步的子类方法
  26. func NewGeneric() Generic {
  27. return &parent{}
  28. // 或者
  29. // return &child{}
  30. }

以上代码示例中,Generic 是一个接口,定义了 V1()V2() 两个方法。parentchild 分别实现了这个接口。你可以根据需要选择返回 parent 或者 child 的实例作为 NewGeneric() 的结果。

英文:

You can't use embedding as a substitute for inheritance. You could use interfaces for that though. Something like:

  1. type Generic interface {
  2. V1() string
  3. V2() string
  4. }
  5. type parent struct {
  6. // ...
  7. }
  8. type child struct {
  9. // ...
  10. }
  11. // parent
  12. func (p *parent) V1() string {
  13. return "parent V1"
  14. }
  15. func (p *parent) V2() string {
  16. return "parent V2"
  17. }
  18. // child
  19. func (c *child) V1() string {
  20. return "child V1"
  21. }
  22. func (c *child) V2() string {
  23. return "child V2"
  24. }
  25. // further child methods
  26. func NewGeneric() Generic {
  27. return &parent{}
  28. // or
  29. // return &child{}
  30. }

答案2

得分: 1

Go语言没有继承(像C++或Java那样),只有组合和接口。所以你的函数只能返回一个类型的结构体(或指针)或接口。初步可以认为接口与C++中的纯虚类几乎相同。

在你的情况下,接口更好。现在取决于程序的其余部分如何处理返回值。如果需要调用几个方法(在Go语言中,我们更喜欢只有几个方法的接口,最理想的情况是只有一个方法)。

例如:

  1. type GenericType interface {
  2. getV1() string
  3. getV2() string
  4. }

但不幸的是,对于所有可以序列化为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.

  1. type GenericType interface {
  2. getV1() string
  3. getV2() string
  4. }

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语言提供了接口来实现泛型类型,并提供类型断言来访问具体类型及其属性。

Playground

  1. type generic interface {
  2. say() string
  3. }
  4. type type1 struct {
  5. msg string
  6. }
  7. func (t type1) say() string {
  8. return t.msg
  9. }
  10. type type2 struct{}
  11. func (t type2) say() string {
  12. return "I'm type 2"
  13. }
  14. func main() {
  15. t1 := type1{"Hey! I'm type1"}
  16. t2 := type2{}
  17. tl := []generic{t1, t2}
  18. for _, i := range tl {
  19. switch v := i.(type) {
  20. case type1:
  21. fmt.Println(v.say())
  22. fmt.Println(v.msg)
  23. case type2:
  24. fmt.Println(v.say())
  25. // fmt.Println(v.msg) Uncomment to see that type2 has no msg attribute.
  26. }
  27. }
  28. }
英文:

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.

Plyground:

  1. type generic interface {
  2. say() string
  3. }
  4. type type1 struct {
  5. msg string
  6. }
  7. func (t type1) say() string {
  8. return t.msg
  9. }
  10. type type2 struct{}
  11. func (t type2) say() string {
  12. return &quot;I&#39;m type 2&quot;
  13. }
  14. func main() {
  15. t1 := type1{&quot;Hey! I&#39;m type1&quot;}
  16. t2 := type2{}
  17. tl := []generic{t1, t2}
  18. for _, i := range tl {
  19. switch v := i.(type) {
  20. case type1:
  21. fmt.Println(v.say())
  22. fmt.Println(v.msg)
  23. case type2:
  24. fmt.Println(v.say())
  25. // fmt.Println(v.msg) Uncomment to see that type2 has no msg attribute.
  26. }
  27. }
  28. }

huangapple
  • 本文由 发表于 2017年3月3日 15:01:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/42572623.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定