Преобразование одного интерфейса в другой

Type assertion b.(YZ) успешен, поскольку *Bar реализует Y и Z. Но z.X() не компилируется: в статическом интерфейсе YZ метода X нет.

Короткий ответ

Что ответить на собеседовании

Type assertion b.(YZ) успешен, поскольку *Bar реализует Y и Z. Но z.X() не компилируется: в статическом интерфейсе YZ метода X нет.

Подробный разбор

Ответ с пояснениями

Условие

В примере есть тип Bar, у которого реализованы методы X(), Y() и Z(). На их основе объявлены два интерфейса: XY, требующий методов X() и Y(), и YZ, требующий методов Y() и Z(). Вопрос: можно ли выполнить приведение переменной типа XY к типу YZ?

type Bar struct{}

func (b *Bar) X() {}
func (b *Bar) Y() {}
func (b *Bar) Z() {}

type XY interface {
 X()
 Y()
}

type YZ interface {
 Y()
 Z()
}

func main() {
 var b XY = &Bar{}
 z := b.(YZ) // Сработает ли это приведение?
 z.X()       // А этот вызов?
 _ = z
}

Опишите, как работает приведение интерфейсов в Go, какие условия должны быть выполнены, и что произойдёт при попытке вызвать метод, отсутствующий в целевом интерфейсе.

Ответ

Type assertion b.(YZ) успешен, поскольку *Bar реализует Y и Z. Но z.X() не компилируется: в статическом интерфейсе YZ метода X нет.

Go проверяет assertion по динамическому типу значения, а доступные методы выражения — по его статическому типу. Поэтому после удаления z.X() можно вызывать z.Y() и z.Z().

Для безопасной проверки неизвестного значения используйте z, ok := b.(YZ): при несовпадении ok будет false вместо panic. Если нужен X, вызывайте его через b или явно проверяйте более широкий интерфейс. Прямое преобразование типа и runtime assertion — разные операции; синтаксис здесь именно assertion.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее