Kevin Deenanauth
Kevin Deenanauth

Reputation: 946

Why does Go allow me to call methods that are not implemented?

Go doesn't seem to enforce the struct adhering to the interface. Why does the following code compile?

package main

type LocalInterface interface {
    SomeMethod(string) error
    SomeOtherMethod(string) error
}

type LocalStruct struct {
    LocalInterface
    myOwnField string
}

func main() {
    var localInterface LocalInterface = &LocalStruct{myOwnField:"test"}

    localInterface.SomeMethod("calling some method")
}

It seems like this should not compile since SomeMethod is not implemented.go build results in no issues.

Running it results in the runtime error:

> go run main.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x20 pc=0x4013b0]

goroutine 1 [running]:
panic(0x460760, 0xc08200a090)
        C:/Go/src/runtime/panic.go:464 +0x3f4
main.(*LocalStruct).SomeMethod(0xc0820064e0, 0x47bf30, 0x13, 0x0, 0x0)
        <autogenerated>:3 +0x70
main.main()
        C:/Users/kdeenanauth/Documents/git/go/src/gitlab.com/kdeenanauth/structTest/main.go:16 +0x98
exit status 2

Upvotes: 6

Views: 3795

Answers (2)

Kevin Deenanauth
Kevin Deenanauth

Reputation: 946

Upon further investigation I found that avoiding embedding gets the proper error handling treatment. That would be preferred in my case:

package main

type LocalInterface interface {
    SomeMethod(string) error
    SomeOtherMethod(string) error
}

type LocalStruct struct {
    myOwnField string
}

func main() {
    var localInterface LocalInterface = &LocalStruct{myOwnField:"test"}

    localInterface.SomeMethod("calling some method")
}

Results in:

.\main.go:13: cannot use LocalStruct literal (type *LocalStruct) as type LocalInterface in assignment: *LocalStruct does not implement LocalInterface (missing SomeMethod method)

Upvotes: 1

kostya
kostya

Reputation: 9559

When a type is embedded (in your example LocalInterface is embedded inside LocalStruct), Go creates a field of the embedded type and promotes its methods to the enclosing type.

So the following declaration

type LocalStruct struct {
    LocalInterface
    myOwnField string
}

is equivalent to

type LocalStruct struct {
    LocalInterface LocalInterface
    myOwnField string
}

func (ls *LocalStruct) SomeMethod(s string) error {
    return ls.LocalInterface.SomeMethod(s)
}

Your program panics with nil pointer dereference because LocalInterface field is nil.

The following program "fixes" the panic (http://play.golang.org/p/Oc3Mfn6LaL):

package main

type LocalInterface interface {
    SomeMethod(string) error
}

type LocalStruct struct {
     LocalInterface
    myOwnField string
}

type A int

func (a A) SomeMethod(s string) error {
    println(s)
    return nil
}

func main() {
    var localInterface LocalInterface = &LocalStruct{
        LocalInterface: A(10),
        myOwnField:     "test",
    }

    localInterface.SomeMethod("calling some method")
}

Upvotes: 7

Related Questions