произойдет ошибка, поскольку тип (* main.XYZ) не реализует интерфейс ABC
Неверно.*main.XYZ
реализует ABC
(иначе abc = xyz
потерпит неудачу во время компиляции, попробуйте переименовать метод, например, b
в c
), но переменная a
содержит указатель nil
(типа*XYZ
).А так как метод XYZ.a()
имеет получатель значения, для вызова этого нужно будет разыменовать значение указателя типа *XYZ
.Но указатель nil
указывает на ничто, его нельзя разыменовать, попытка сделать это приводит к панике во время выполнения, как вы уже испытали.
Если вы инициализируете xyz
в начале с не- nil
указатель, он будет работать:
var xyz *XYZ = new(XYZ)
Попробуйте на Go Playground .
Также обратите внимание, что если XYZ.a()
и XYZ.b()
будетесли у вас есть указатель, то он также будет работать, если xyz
равен nil
:
func (xyz *XYZ) a() string {
return "XYZ"
}
func (xyz *XYZ) b() int {
return 123
}
func main() {
var xyz *XYZ
// ...
Попробуйте на Go Playground .Причина этого в том, что если получатели являются указателями, указатель nil
не нужно разыменовывать для вызова методов с указателями получателей, поэтому паника во время выполнения не возникает.Конечно, если в методах вы бы ссылались на поля XZY.aa
или XYZ.bb
, это было бы паникой во время выполнения, но ваша текущая реализация методов не делает этого, поэтому она работает.