首页 > 解决方案 > Go中没有方法的结构的多态性

问题描述

我正在使用 Go 开发几个 Web 服务器项目,并且我一直面临一个常见问题。我知道我们可以通过接口和方法在 Go 中实现多态性之类的东西,但是很多时候我有一个场景,我需要在一些数据持有者结构上实现多态性,这些数据持有者结构(可能)只有一些公共字段,而根本没有方法。

例如考虑一个故事写作平台,每个用户都可以写短篇小说和小说:

type ShortStory struct {
    Name string
    ID   int
    Body string
}

type LongStory struct {
    Name     string
    ID       int
    Chapters []string
}

现在我只想拥有一个数据层函数,比如说GetStories(),它从数据库中获取用户编写的所有故事。

func GetStories(id int) []SOME_TYPE {
    ...
}

真的没有我想在我的ShortStoryLongStory结构上使用的方法。我知道我可以添加一个虚拟方法并让它们满足某个Storier接口,然后将该接口用作返回类型。但是由于在数据容器模型上没有我想要的方法,因此为语言添加一个虚拟方法以启用一个特性,对我来说似乎是一个糟糕的设计选择。

我也可以让函数 return []interface{},但这与我相信的“类型化语言”的整个​​想法背道而驰。

另一种方法是有两个单独的GetShortStories()andGetLongStories()方法,它们返回自己类型的切片。但是在某些时候,我最终想将这两个切片合并为一个,然后我又需要一个[]interface{}. 是的,我可以返回如下 JSON:

{
    "short_stories" : [...],
    "long_stories" : [...]
}

但我希望我的 json 像:

[{...}, {...}, {...}]

而且我不会因为语言的限制而改变我的 API!

我不是围棋专家,所以我在这里遗漏了什么吗?是否有一种Go-ish方法,或者 Golang 方面的语言设计真的很糟糕?

标签: gopolymorphismweb-development-server

解决方案


If you cannot express what you want to do using the features of a language, you should first try to change the way you structure your program before blaming the language itself. There are concepts that cannot be expressed in Go but can be expressed well in other languages, and there are concepts you cannot express well in other languages but you can in Go. Change the way you solve the problem to effectively use the language.

One way you can address your problem is using a different type of struct:

type Story struct {
    Name     string
    ID       int
    ShortBody string
    Chapters []string
}

If the Chapters is empty, then it is a short story.

Another way:

type Story struct {
   Name string
   ID int
   Content StoryContent
}

type StoryContent interface {
   Type() string
}

type ShortStory interface {
   StoryContent
   Body() string
}

type LongStory interface {
   StoryContent
   Chapters() []string
}

etc.


推荐阅读