Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

go

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
like image 805
Kevin Deenanauth Avatar asked Apr 21 '16 03:04

Kevin Deenanauth


1 Answers

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")
}
like image 190
kostya Avatar answered Sep 28 '22 07:09

kostya