Есть два способа сделать это: один, вместо использования пустого интерфейса, вы используете надлежащий родительский интерфейс для объявления среза:
// Maintains the created objects
var availableObjs []Parent
Обратите внимание, что наименование Parent
для вашего интерфейса говорит о том, что вы приближаетесь к интерфейсам с концепцией наследования, которую мы не используем в Go. Вы должны думать об интерфейсах больше как о поведении. В этом конкретном случае вы хотите представить поведение чего-либо, способного «отображать», поэтому вы вполне можете назвать интерфейс Displayer
.
Это соглашение об именах, добавляющее -er
к имени интерфейса, является очень распространенным шаблоном в Go, хотя иногда вы получаете некоторые странные имена:)
В том же смысле структуры Child
на самом деле не являются дочерними элементами родительского интерфейса, они просто являются структурами, которые неявно удовлетворяют интерфейсу.
Они могут одновременно удовлетворять любому количеству интерфейсов. Например, если бы у них был метод String (), они бы также удовлетворяли интерфейсу fmt.Stringer
.
Теперь второй вариант - использовать утверждение типа, либо с оператором switch, либо с оператором типа:
switch t := obj.(type) {
case Parent:
t.Display() // note that 't' is the new typed variable
}
Или
t, ok := obj.(Parent)
if ok {
t.Display()
}
Обратите внимание, что указанную выше переменную ok
можно опустить, но в этом случае код будет паниковать, если утверждение типа не совпадает.