Как передать массив с несколькими типами в один функционал - PullRequest
0 голосов
/ 13 марта 2019

У меня есть несколько структур

type Base struct {
    Id string
    Name string
    Code string
}
type Country struct {
    Base
    ...
}
type City struct {
    Base
    ...
}

И мне нужно сделать функцию, которая принимает массив City или Country. В настоящее время у меня есть одна функция для каждого типа, которая делает то же самое, и я думаю, что это не лучший / хороший способ сделать это!

Спасибо

Ответы [ 2 ]

3 голосов
/ 13 марта 2019

Похоже, вы пытаетесь воссоздать наследование классов в Go.Go не имеет наследования классов специально.Не пытайтесь воссоздать его.Я полагаю, вы думаете: «Страна - это база».Это не правильно.Страна Встраивает База.Это не одно и то же.Это имеет значение для того, как вы называете вещи.В этом случае кажется, что «База» - это действительно «метаданные местоположения», поэтому мы назовем это так.

type LocationMeta struct {
    id   string
    name string
    code string
}

И вам нужен интерфейс для работы со всеми видами местоположений.

type Location interface {
    Id() string
    Name() string
    Code() string
}

Мы можем согласовать LocationMeta с Location, хотя это, возможно, немного странно (метаданные действительно a Location?).Но это работает.

func (b LocationMeta) Id() string {
    return b.id
}

func (b LocationMeta) Name() string {
    return b.name
}

func (b LocationMeta) Code() string {
    return b.code
}

И мы можем встроить LocationMeta в Город:

type City struct {
    LocationMeta
}

И бесплатно, Город теперь соответствует Location.

Тем не менее,обычно вы не беспокоитесь о таком типе встраивания для такой маленькой вещи без какой-либо логики.Это действительно излишне;Я просто демонстрировал это, потому что вы, кажется, используете это.Обычно вы просто настраиваете каждый тип самостоятельно:

type Country struct {
    id   string
    name string
    code string
}

func (c Country) Id() string {
    return c.id
}

func (c Country) Name() string {
    return c.name
}

func (c Country) Code() string {
    return c.code
}

Самое замечательное в Go состоит в том, что его не волнует, как вы соответствуете интерфейсу.Город и Страна оба соответствуют Местоположению совершенно по-разному, и это совершенно нормально.

Итак, вы можете создать город:

boston := City{LocationMeta{id: "bos", name: "Boston", code: "bos"}}

Видите, как это странно?Мы должны создать LocationMeta из-за встроенного объекта.Иногда это может стоить (и невероятно мощно), но я бы, наверное, сделал и город и страну по-деревенски (без LocationMeta):

us := Country{id: "us", name: "USA", code: "us"}

Но, тем не менее, они оба локации,поэтому мы можем поместить их в срез:

locations := []Location{boston, us}

и передать их вещам:

func printLocations(locations []Location) {
    fmt.Println(locations)
}

printLocations(locations)

Площадка с этим кодом

Детская площадка с использованием встраивания для всего

Детская площадка с более типичным подходом с простыми структурами

1 голос
/ 13 марта 2019

я уже опубликовал это в комментариях, но вы можете сделать это

func myfunc(in interface{}) {
    switch in.(type) {
    case []Country:
        // country logic here
    case []City:
        // city logic here
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...