Вы объявляете, но явно не определяете переменную с именем t
в обоих случаях.Если вы не укажете значение, нулевое значение для типа переменной будет присвоено
Нулевое значение для всех типов указателей, включая *T
, равно nil.Нулевое значение для типа структуры - это значение этой структуры со всеми полями, для которых установлены нулевые значения.
Когда хранилище выделено для переменной [...] и не предусмотрена явная инициализация,переменной или значению присваивается значение по умолчанию.Каждый элемент такой переменной или значения устанавливается в нулевое значение для его типа: false для логических значений, 0 для числовых типов, «» для строк и nil для указателей, функций, интерфейсов, слайсов, каналов и карт.Эта инициализация выполняется рекурсивно, поэтому, например, каждый элемент массива структур будет обнулять свои поля, если не указано значение.
https://golang.org/ref/spec#The_zero_value
Следовательно, это сохраняет ноль взначение интерфейса i
:
var i interface{ M() }
var t *T
i = t
// i stores nil
И это сохраняет значение структуры в значении интерфейса i
:
var i interface{ M() }
var t T
i = t
// i stores T{S:""}
Так что в первом случае вызывается (nil).M()
(который паникует), а во втором случае (T{}).M()
называется.