Потому что Bar не реализует stringify
* Bar делает.
Если вы удалите реализацию stringify
из Foo, вы получите «{}».
Аналогично, когда вы пишете fmt.Println(Bar{})
, это означает, что оно будет выглядеть примерно так: func (Bar) String()
и не func (*Bar) String()
Additioanlly, история отличается, когда вы пишете fmt.Println(&Foo{})
, вы можете подумать, что она напечатает «{}», потому что нет func (*Foo) String()
, но она напечатает «Foo».
Для этого вам придется понимать интерфейсы.Это мой опыт, поэтому, пожалуйста, проведите собственное исследование тоже.Функция fmt.Print
использует String () из stringify.Таким образом, на самом деле String () вызывается не для вашей структуры, а для переменной типа stringify.
Тип интерфейса может содержать тип (который его реализовал) или указатель на него, если он был реализован с помощью приемника значения.Вот почему оба Foo{}
и &Foo{}
работают. Тип интерфейса
может содержать указатель типа (который его реализовал), только если он был реализован с помощью приемника указателя.Зачем?Потому что, когда вы реализуете интерфейс с указателем приемника, ему нужен адрес, который может быть предоставлен только с указателем.Вот почему работает только &Bar{}
, а не Bar{}