Go中struct嵌套与面向对象以及上下文


我一直倾向于尽量避免Go struct结构体嵌入,因为我发现这样做会增加阅读难度,因为这个 "上帝结构体god struct "恰好实现了大量独立的接口,并被传递到很多地方。不过我还是想听听其他人的意见。

您对结构嵌入(尤其是实现trait接口时)有什么看法?


Reddit网友讨论:

每次我这样做我都会后悔。我发现它们非常难以阅读。

====================================

上次我设计一些严重依赖结构嵌入的东西时,我迷失了几周,最终把它全部撕掉了。
我认为这是一个教训。当我建造它的时候,我对整个肮脏的行业产生了一种令人毛骨悚然的厌恶。

====================================

结构嵌入的一个很好的用例是限制对数据的访问并实现职责分离。如果特定代码需要对较大数据的子集进行操作,有时使用结构嵌入会更容易完成。一个例子是处理配置:

type AWSConfig {
  Region string `env:"AWS_REGION"`
  S3Bucket string `env:
"S3_BUCKET"`
}

type DbConfig {
  Username string `env:
"DB_NAME"`
  Host string `env:
"DB_HOST"`
}

type Config {
  AWSConfig
  DbConfig
}

// ...

cfg := readConfig()
// Reads everything
m1 := NewModule1(cfg.AWSConfig)
// Only concerned with AWS
m2 := NewModule2(cfg.DbConfig)  
// Only concerned with DB

====================================

我认为如果您的结构代表一个真正的业务实体并且它具有组成部分,那么它就有意义。我觉得它有点麻烦,但我并不反对它有时很好地代表一些真实事物的想法。

====================================

接口一直存在,结构几乎从不存在

====================================

据我所知,我们在应用程序中只有两个地方使用了结构嵌入:

  • 具有通用数据集的模型(也就是说,您希望拥有一个包含 int ID、created_at 和 Updated_at 等内容的基本模型)。应该小心谨慎,但看起来效果还不错。在这种情况下可能更愿意明确,但它也从未引起重大问题,所以......
  • 在我们的企业项目中扩展我们的 FOSS 项目的数据库 god 结构和 God 接口。问题是我们首先有上帝对象,但是当你坚持使用它时,嵌入接口和结构来创建满足调用的超集,它就很重要了。非常恶心,仅用作临时解决方法

====================================

除了实现接口,我不知道还有其他原因。

有一个用例我有时会用到,但用起来还是觉得恶心。那就是:联合类型union types。

我制作了一个空结构体,其中的方法什么也不做,只是有一个唯一的名字。然后,我用这个方法创建一个接口,任何嵌入这个空结构的东西都可以实现这个接口。因此,该接口类型就是嵌入该结构的所有东西的联合。

我使用联合类型的主要目的是异构树。节点 A 可以有 B 或 C 作为子节点,B 可以有 A 作为子节点,等等。

====================================
banq注:

  • 结构struct + 接口trait = DDD聚合 =>Being in Context(上下文)
  • Data + interactive =>Being in Context (DCI
  • 数据 + 单一职责 = 对象  =>Being in Context(上下文) 
  • 数据结构 + 算法 = 应用 =>Being in Context(上下文) 
  • MVC:M模型数据 + V视图动作事件 = C控制器 =>Being in Context(上下文) 
  • DDD聚合 = 上帝结构体god struct (没有考虑上下文、场景的聚合都会变成上帝对象