2015-05-22 121 views
48

我很困惑,爲什麼失敗,編譯:爲什麼不能接口指針接收器來實現

不可能類型斷言: FAZ沒有實現美孚(酒吧方法指針接收器)

,如果我做了接收器Faz.Bar一個FAZ值,而不是一個FAZ指針然後它編譯罰款,但我認爲它總是最好有指針接收器,以便值不被複制周圍?

package main 

import (
    "log" 
) 

func main() { 
    foo := New().(Faz) 
    log.Println(foo) 
} 

type Foo interface { 
    Bar() string 
} 

func New() Foo { 
    return &Faz{} 
} 

type Faz struct { 
} 

func (f *Faz) Bar() string { 
    return `Bar` 
} 
+5

[看到這篇文章](http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go)。 –

+3

作爲一個側面說明:@KerrekSB引用的文章有助於我理解,當Go抱怨「MyFoo沒有實現Foo(Bar方法有指針接收器)」時,這並不意味着你無法使用指針接收器。這意味着實現'Bar'的'MyFoo'的方法_none_應該有指針接收器,或者_all_必須。這是一個與@xor1不同的問題,但其他人可能會發現這個問題,因爲他們正在混合他們的接收器類型(像我一樣),而不理解他們正在得到的錯誤。 – Hephaestus

回答

51

因爲它*FazFaz

func main() { 
    foo := New().(*Faz) 
    log.Println(foo) 
} 
+0

我敢肯定,我嘗試過:s,非常感謝:) – 0xor1

+4

他們可以是*法茲或法茲,但他們都必須匹配。如果你打算'返回Faz {}'或* Faz,如果你打算'return&Faz {}',定義它們全部Faz。他們如何維護狀態被認爲是基本上隱藏於用戶的實現細節。 –

4

我認爲這個問題的答案需要更多的回顧文法的方法,以及如何通過軟件工程實現它。 (請原諒,在簡化)


首先是什麼types快速閃回?
它們只是帶有編譯器邏輯的內存塊。 arraystring不同的地方在於編譯器允許我們對這些內存塊進行處理。 (想想更深入,你可能會開始意識到strongly typeddynamically typed語言之間的真正區別。)

現在接下來你需要認識到,指針是每種說法自己的類型。
*variable是與variable不同的內存塊(又稱類型)。只是編譯器總是假定*variable的內容總是要成爲聲明右側的內存塊的地址,以及它所施加的其他限制/功能。

然後讓我們回顧一下接口是什麼。
僞科學定義:任何第一類公民具有特定類型的一組要求。 翻譯到軟件工程,其具有與之相關聯的作爲在合同(interface)中描述的相同的存儲器結構(回想structure packing)可以作爲與類型名稱圍繞傳遞存儲器(類型)的任何塊合同提到。


現在你可以開始意識到,當你說

func (f *Faz) Bar() stringf「記憶的阻攔拿着一個函數,其中f的類型是指針Faz

哪裏區域

func (f Faz) Bar() stringf的內存塊,其中f的類型是Faz

所以你是說*Faz類型的變量滿足合同時,那麼你怎麼能認爲Faz類型的變量將有資格在代碼中的接口類型?選擇滿足您的合同的人,只有該類型可以在您的代碼中使用接口類型。

+0

我不同意你的解釋一致,下面的程序運行(輸入* foo的滿足字符串()的Foo類型定義):包裝主 進口( \t 「FMT」 ) Foo類型的struct {} FUNC (F FOO)字符串(){字符串 \t返回 「111」 } FUNC主(){ \t F:= FOO {} \t一個:=&FOO {} \t變種小號fmt.Stringer \t小號= a \t s = f \t fmt.Println(f.String(),a.String(),s) } –

+0

請參閱https://golang.org/ref/spec#Method_sets –

相關問題