Why does method signature have to perfectly match interface method

I think your understanding of interface isn't sound. Interface{} itself is a type. It consists of two things : underlying type and underlying value.

Golang doesn't have overloading. Golang type system matches by name and requires consistency in the types

So, when you are defining a function taking a interface type as a parameter:

foo(interface {})

This is a different function from a function taking int type:

foo(int)

So you should change the following line to

func (s S) foo(i interface{}) {
    fmt.Println(i)
}

Or better yet to this:

type I interface {
    foo()
}

type S struct {
    I int
}

func (s S) foo() {
    fmt.Println(s.I)
}

func main() {
    var i I = S{2}
    i.foo()
}

Tags:

Go