2016-04-21 120 views
3

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 

回答

6

當一個類型被嵌入(在你的榜樣LocalInterface嵌入內LocalStruct),圍棋創建嵌入類型的字段,並促進它的方法封閉類型。

所以下面的聲明

type LocalStruct struct { 
    LocalInterface 
    myOwnField string 
} 

因爲LocalInterfacenil相當於

type LocalStruct struct { 
    LocalInterface LocalInterface 
    myOwnField string 
} 

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

你的程序恐慌與零指針引用。

下面的程序「修復」恐慌(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") 
} 
+0

我已經忘記了這是一個隱藏字段和零指針異常非常有意義。感謝您爲說明修復引入了另一種類型的內容來完成界面! –

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: cannot use LocalStruct literal (type *LocalStruct) as type LocalInterface in assignment: *LocalStruct does not implement LocalInterface (missing SomeMethod method)