关于如何在 Golang 中实现抽象类 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
LoremIpSum

关于如何在 Golang 中实现抽象类

  •  
  •   LoremIpSum 2022 年 6 月 13 日 3887 次点击
    这是一个创建于 1411 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设现在我们定义了一个接口I,有两个方法Foo,Bar, 结构体Parent实现了 Foo,而Bar作为抽象方法由子类实现, 示例代码如下:

    package main type I interface { Foo() Bar() } type Parent struct { I } func (p *Parent) Foo() { p.Bar() } type Child struct { Parent } func (c *Child) Bar() { fmt.Println("Child.Bar()") } func main() { c := &Child{ Parent: Parent{}, } c.I = c // 如果注释掉这几句会提示空指针异常 c.Foo() } 

    输出如下:

    Child.Bar() 

    问题: 1.上面的代码实现了类似Java风格的抽象类,但是在main方法中的这句代码没看懂c.I = c,这句代码的本质是做了什么事情?为什么c.I = c就会报空指针异常

    11 条回复    2022-06-14 09:38:42 +08:00
    doomfirst
        1
    doomfirst  
       2022 年 6 月 13 日
    你不觉得你为了在 go 实现 java 的抽象类 写的很别扭么?
    akaHenry
        2
    akaHenry  
       2022 年 6 月 13 日   7
    不要用 Java 的思维来写 Go.

    理解好 Go Interface 接口使用. 就够了.

    之所以只有 Java 语言, 特别爱强调设计模式, 是 Java 的设计缺陷, 才需要显式打补丁(不是优点, 不要搞反了).

    其他语言, 设计模式, 早就融入语言本身的设计.

    Go Interface, 是面向接口编程的典范. 非常漂亮. 兼顾优雅 /简洁 /易用.

    理解 Go 很简单. 核心就 2 点. 面向接口(interface) + 面向队列(channel) 编程. (沙雕泛型 generic, 先跳过)

    面向接口(interface) = 面向动作(action), 数据和操作分离. 聚焦对操作(action)作抽象. 以操作为主, 数据来适配操作.

    面向队列(channel) = MQ(kafka) = 生产者 /消费者模型. 你可以把 go channel, 当成内置的 kafka 来理解, 使用方式也一样.

    so. go 的精华, 只有这么多. 剩下的部分, 都是裁剪 c 语言. (垃圾泛型除外)
    rrfeng
        3
    rrfeng  
       2022 年 6 月 13 日 via Android
    你把 I 放到 parent 里是个什么意思。。。。
    Hyvi
        4
    Hyvi  
       2022 年 6 月 13 日 via iPhone
    你把内嵌结构体理解成继承 /接口实现了。看看 embeded struct
    HiShan
        5
    HiShan  
       2022 年 6 月 13 日
    本质上是让 Parent 继承 I 接口的具体实现,从而实现调用到子类的实现。。不过这样写实在是太奇怪了。。。
    PS:go 设计的只有简单与漂亮\简单不沾边
    HiShan
        6
    HiShan  
       2022 年 6 月 13 日
    @HiShan 漂亮\优雅
    fo0o7hU2tr6v6TCe
        7
    fo0o7hU2tr6v6TCe  
       2022 年 6 月 13 日
    近几年新出来的一些语言,不要参考 java 来学习
    LoremIpSum
        8
    LoremIpSum  
    OP
       2022 年 6 月 13 日
    @rrfeng 这样写可以实现这功能,但是底层原理不知道为什么
    akaHenry
        9
    akaHenry  
       2022 年 6 月 13 日   1
    多说一句. Go 和 Rust 等更现代的语言设计, 都是重视 组合 /嵌套 > 类继承.

    Go 的 接口(interface) 设计, 都是 `组合` 的方式来扩展功能.

    不要被 `类继承` 束缚思维. `类继承`, 是糟糕的东西.

    不要总是想定义很大的类 struct (数据+方法过多).

    尽量切分小类. 标准化操作 = 抽象接口方法(interface).

    另外, go struct{}, 可以作为命名空间 namespace 使用 = 裸类(没数据, 只有方法).

    小模块, 搭积木, 自由组合. 可以写出非常干净 /清晰的代码.
    akaHenry
        10
    akaHenry  
       2022 年 6 月 13 日
    理性状态: 接口设计(interface) 和 数据(data), 应该是正交的.

    推荐读 go-micro 这个项目源码来学习如何写 go + 设计大型框架系统.

    go-micro 的代码写的非常非常漂亮.
    mengdodo
        11
    mengdodo  
       2022 年 6 月 14 日
    不要用设计模式去包裹 go, 那不是它
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5410 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 298ms UTC 07:02 PVG 15:02 LAX 00:02 JFK 03:02
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86