go

Why does method signature have to perfectly match interface method


I began to learn Go and have trouble understanding the following:

package main

import "fmt"

type I interface {
    foo(interface {})
}

type S struct {}

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

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

This fails with:

cannot use S literal (type S) as type I in assignment:
        S does not implement I (wrong type for foo method)
                have foo(int)
                want foo(interface {})

I don't understand why Go doesn't accept the foo(int) signature given the fact that int implements interface {}. Can anyone help with an explanation?


Solution

  • 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()
    }