Вот с чем я столкнулся, и я не могу понять, почему ошибка:
package main
import (
"fmt"
)
// define a basic interface
type I interface {
get_name() string
}
// define a struct that implements the "I" interface
type Foo struct {
Name string
}
func (f *Foo) get_name() string {
return f.Name
}
// define two print functions:
// the first function accepts *I. this throws the error
// changing from *I to I solves the problem
func print_item1(item *I) {
fmt.Printf("%s\n", item.get_name())
}
// the second function accepts *Foo. works well
func print_item2(item *Foo) {
fmt.Printf("%s\n", item.get_name())
}
func main() {
print_item1(&Foo{"X"})
print_item2(&Foo{"Y"})
}
Две идентичные функции принимают один аргумент: указатель либо на интерфейс, либо на структуру, реализующую его.
Первый, который принимает указатель на интерфейс, не компилируется с ошибкой item.get_name undefined (type *I is pointer to interface, not interface).
Переход с *I на I решает проблему.
Я хотел бы знать, ПОЧЕМУ разница? Первая функция очень распространена, поскольку позволяет использовать одну функцию с различными структурами, если они реализуют интерфейс I.
Кроме того, почему функция компилируется, когда она определена для приема I, но фактически получает указатель (&Foo{})? Должна ли функция ожидать чего-то вроде Foo{} (т.е. НЕ указателя)?
Нет причин использовать указатель на интерфейс. Просто удалите их все, и проблем не будет.

Быстрое решение этой проблемы - сделать так, чтобы print_item1 просто принимал I, а не указатель на I.
func print_item1(item I)
Причина этого в том, что *Foo удовлетворяет интерфейсу I, но помните, что *Foo не является *I.
Я настоятельно рекомендую прочитать Рассказ Кокса о реализации интерфейсов
Причина правильная, я бы не стал предлагать принимать I, не зная контекста.