为什么Go允许我调用未实现的方法?

时间:2016-04-21 03:10:25

标签: go

Go似乎没有强制遵守接口的结构。为什么以下代码编译?

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")
}

由于SomeMethod未实现,因此似乎无法编译。go build不会导致任何问题。

运行它会导致运行时错误:

> 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

2 个答案:

答案 0 :(得分:7)

当嵌入了一个类型时(在你的示例LocalInterface中嵌入了LocalStruct),Go会创建一个嵌入类型的字段并将其方法提升为封闭类型。

以下声明

type LocalStruct struct {
    LocalInterface
    myOwnField string
}

相当于

type LocalStruct struct {
    LocalInterface LocalInterface
    myOwnField string
}

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

由于LocalInterface字段为nil,您的程序会因为nil指针取消引用而发生恐慌。

以下程序“修复”恐慌(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")
}

答案 1 :(得分:0)

经过进一步调查,我发现避免嵌入会得到正确的错误处理处理。在我的情况下,这将是首选:

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")
}

结果:

  

。\ main.go:13:在赋值时不能使用LocalStruct文字(类型* LocalStruct)作为LocalInterface类型:           * LocalStruct没有实现LocalInterface(缺少SomeMethod方法)