dsa89029 2017-03-02 09:13
浏览 73
已采纳

在golang中返回self struct克隆(不反映)

there are two structs,
Foo has a Clone() method
Bar is inherit from Foo

package main

import "fmt"

type IF interface {
    Clone() IF
}

type Foo struct {
    i int
}

func (this *Foo) Clone() IF {
    c := *this
    return &c
}

type Bar struct {
    Foo
}

func main() {
    t := &Bar{}
    c := t.Clone()
    fmt.Printf(`%T `, t)
    fmt.Printf(`%T `, c)
}

https://play.golang.org/p/pFn348aydW

output is

*main.Bar *main.Foo

but I want clone a Bar, not Foo
I must add Bar.Clone() exactly the same as Foo.Clone()

func (this *Bar) Clone() IF {
    c := *this
    return &c
}

https://play.golang.org/p/J6jT_0f1WW

Now the output is what I want

*main.Bar *main.Bar

If I will write lots of struct like Bar, I won't write lots of Clone(), what I can do ? It is best not to use reflect

  • 写回答

2条回答 默认 最新

  • douling0053 2017-03-02 09:16
    关注

    Go doesn't have inheritance, this is composition, not inheritance, which is why you're getting frustrated. Bar doesn't inherit from Foo, it embeds Foo, which is very different. When embedding, the embedded methods act on the embedded struct, not the wrapper, so yes you're correct, you must add a bar Clone() if you want something returning a Bar.

    Probably it's better to step back and consider why you're embedding Foo though - don't try to use Foo like a base class, think of it more as a module of code you're importing (self-contained, refers only to data in Foo, not in Bar). So obviously this is just a toy example, but to extend it to illustrate what Foo does:

    type Foo struct {
        i int
    }
    
    func (f *Foo) String() string {
        if f.i > 0 {
            return fmt.Sprintf("val:%d", f.i)
        }
        return ""
    }
    
    type Bar struct {
        Foo
    }
    
    // Bar conforms to Stringer by virtue of embedding Foo
    // using the Foo data stored in i 
    type Stringer interface {
        String() string
    }
    
    func Print(b Stringer) {
        fmt.Printf("%s", b)
    }
    
    func main() {
        b := &Bar{}
        Print(b) // Outputs empty string
        b.i = 4
        Print(b) // Outputs val:4
    }
    

    https://play.golang.org/p/tNWPVw79aa

    So you can use Foo methods but they should only relate to contents of the Foo struct, and you should probably just keep everything in Bar till you're very sure you need Foo for some reason, then break it out - Go will guide you towards minimal complexity, and does not support inheritance for that reason.

    In languages supporting inheritance you might start your design process by producing a lovely big taxonomy of classes with abstract base classes factories etc. In go you start by considering the data and behaviour attached to it or acting on it.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作