Полиморфизм на структурах без методов в Go - PullRequest
0 голосов
/ 24 апреля 2020

Я работаю над несколькими проектами веб-сервера в Go, и есть общая проблема, с которой я всегда сталкиваюсь. Я знаю, что мы можем достичь чего-то вроде полиморфизма в 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 {
    ...
}

На самом деле нет никаких методов, которые я бы хотел использовать в своих структурах ShortStory и LongStory. Я знаю, что могу добавить фиктивный метод и позволить им удовлетворить некоторый интерфейс Storier, а затем использовать этот интерфейс в качестве возвращаемого типа. Но так как в модели контейнера данных я не хотел бы использовать какой-либо метод, добавление фиктивного метода только для того, чтобы язык включал функцию, кажется мне неудачным выбором при проектировании.

Я также могу сделать возврат функции []interface{}, но я полагаю, что это противоречит самой идее "типизированного языка".

Другой способ - использовать два отдельных метода GetShortStories() и GetLongStories(), которые возвращают фрагмент своего собственного типа. Но в какой-то момент я, наконец, хотел бы объединить эти два фрагмента в один, и там мне снова понадобится []interface{}. Да, я могу вернуть JSON как:

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

Но я хочу, чтобы мой json был похож на:

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

И я бы не стал менять свои API из-за ограничения языка!

Я не профессионал в Go, поэтому я что-то здесь упускаю? Есть ли Go -i sh подход к этому или действительно плохой языковой дизайн на стороне Golang?

1 Ответ

0 голосов
/ 24 апреля 2020

Если вы не можете express делать то, что вы хотите сделать, используя функции языка, вы должны сначала попытаться изменить структуру вашей программы, прежде чем обвинять сам язык. Есть понятия, которые не могут быть выражены в Go, но могут быть хорошо выражены на других языках, и есть понятия, которые вы не можете express хорошо на других языках, но вы можете в Go. Измените способ решения проблемы, чтобы эффективно использовать язык.

Один из способов решения проблемы - использовать другой тип структуры:

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

Если Chapters пусто тогда это небольшой рассказ.

Другой способ:

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
}

et c.

...