#go
#Вперед
Вопрос:
У меня есть несколько структур
type Base struct {
Id string
Name string
Code string
}
type Country struct {
Base
...
}
type City struct {
Base
...
}
И мне нужно создать функцию, которая принимает массив города или страны. В настоящее время у меня есть одна функция для каждого типа, которая выполняет одно и то же, и я думаю, что это не лучший способ сделать это!
Спасибо
Комментарии:
1. вы можете создать метод для типов, эти методы могут иметь одинаковое имя. но если country и city — это одна и та же структура, тогда зачем создавать 2 структуры?
2. вы могли бы попытаться заставить функцию принимать тип интерфейса []{}
3. @Pizzalord Каждая структура связана с Gorm, и иногда они представляют собой несколько дополнительных полей ! Что вы подразумеваете под методом создания для типов?
4. @SivaGuru Я пробовал, не работает для array -> Не удается использовать ‘предложение. Страны (введите []Country) как интерфейс типа []{}
5. @Clowning вы могли бы сделать функцию x (интерфейс массива{}) вместо x (интерфейс массива []{}), поскольку вы отправляете 1 интерфейс, который является массивом
Ответ №1:
Похоже, вы пытаетесь воссоздать наследование классов в Go. Go специально не использует наследование классов. Не пытайтесь воссоздать его. Я полагаю, вы думаете, что «Country — это база». Это неверно. Страна встраивает базу. Это не одно и то же. Это имеет значение для того, как вы называете вещи. В этом случае кажется, что «База» на самом деле является «метаданными местоположения», поэтому мы будем называть это так.
type LocationMeta struct {
id string
name string
code string
}
И вам нужен интерфейс для работы со всеми типами местоположений.
type Location interface {
Id() string
Name() string
Code() string
}
Мы можем привести LocationMeta в соответствие с 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
}
И бесплатно, город теперь соответствует местоположению.
Тем не менее, обычно вы не утруждаете себя такого рода внедрением для такой маленькой вещи без собственной логики. Это действительно перебор; я просто демонстрировал это, потому что вы, похоже, этим пользуетесь. Обычно вы просто соответствуете каждому типу самостоятельно:
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 из-за встроенного объекта. Иногда это может стоить того (и невероятно мощно), но я бы, вероятно, сделал и City, и Country по-деревенски (без LocationMeta):
us := Country{id: "us", name: "USA", code: "us"}
Но все равно, это оба местоположения, поэтому мы можем поместить их в срез:
locations := []Location{boston, us}
И передать их вещам:
func printLocations(locations []Location) {
fmt.Println(locations)
}
printLocations(locations)
Игровая площадка, использующая встраивание для всего
Игровая площадка более типичного подхода с использованием только структур
Ответ №2:
я уже опубликовал это в комментариях, но вы можете сделать это
func myfunc(in interface{}) {
switch in.(type) {
case []Country:
// country logic here
case []City:
// city logic here
}
}