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条)

报告相同问题?

悬赏问题

  • ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历