2014-04-07 52 views
3

我最近了解到,在net/http包中,有一種使用模式使我最困惑。它是功能類型轉換。它是這樣的:轉換功能到另一種類型(功能鑄造)在轉到

(function a) ->convert to-> (type t) 
(type t) ->implentments-> (interface i) 

所以,如果有這需要接口i作爲其參數的函數,它會調用該函數,這是net/http實現它的方式。

但是當我寫自己的代碼時,我對這種模式有很多誤解。我的代碼是這樣的:

package main 

import (
    "fmt" 
) 

type eat interface { 
    eat() 
} 
type aaa func() 

func (op *aaa) eat() {//pointer receiver not right 
    fmt.Println("dog eat feels good") 
} 

/////////////////////////////////////////////// 
func dog() { 
    fmt.Println("I'm a dog") 
} 
/////////////////////////////////////////////// 

func feelsGood(a eat) { 
    a.eat() 
} 

func main() { 
    b := aaa(dog) 
    feelsGood(b) 
} 

//error:aaa does not implement eat (eat method has pointer receiver) 

類型AAA級方法吃,同樣的函數名和參數簽名,符合接口吃的規則,但爲什麼它給這個錯誤?接收器是否重要?

的另一個問題是,只有一個功能和類型,但不包括接口,代碼是這樣的:

package main 

import (
    "fmt" 
) 

type aaa func() 

func (op *aaa) eat() { 
    op() 
} 

/////////////////////////////////////////////// 
func dog() { 
    fmt.Println("I'm a dog") 
} 
/////////////////////////////////////////////// 

func main() { 
    obj:=aaa(dog) 
    obj.eat() 
} 
//error:cannot call non-function op (type *aaa) 

首先,是op一個匿名函數,無論錯誤的?

其次,刪除星號後效果很好,但爲什麼? opaaa類型的實例,接收者是opop代表函數dog()嗎? http包使用相同的方式使用f(w,r),但它有點難以理解。 op是一種類型,一個實例還是一個匿名函數?

這似乎是我對功能轉換的理解不正確,但我也檢查了很多谷歌上的帖子,沒有人能教會我如何去思考並正確使用它。謝謝!

回答

1

對於您的問題的第一部分:請參閱http://golang.org/doc/faq#different_method_sets,這比我能做的更好。你甚至可以在這個問題上搜索stackoverflow和golang-nuts郵件列表,因爲這經常會出現。

第二個就是一樣恕我直言:aaa沒有eat-方法(只有*aaa有)。

7

問題1:

在Go中,對於類型T(等你的情況AAA),T*T具有不同的方法集。

因此,類型T的值只能訪問方法:

func(t T)Foo() { ... } 

雖然類型爲* T的值可以訪問這兩種方法:

func(t T)Foo() { ... } 
func(t *T)Bar() { ... } 

你的情況,你有兩個選擇。要麼你申報aaaeat方法,而不是OD *aaa

func (op aaa) eat() { 
    op() 
} 

或傳遞指針bfeelsGood

feelsGood(&b) 

問題2:

是的,這個問題是與第一個有關。但在這種情況下,您可以訪問該方法,因爲obj.eat()將是(&obj).eat()的縮寫。

你的問題在於你不能在函數指針(op * aaa)上調用一個函數。你的選擇是要麼創建方法的aaa代替*aaa

func (op aaa) eat() { 
    op() 
} 

還是要呼籲值op功能,而不是指針:

func (op *aaa) eat() { 
    (*op)() 
} 
+0

但是,我只聲明T類,* T類型甚至不存在,那麼,一個不存在的* T類型如何實現一個接口?甚至更多,即使* T類型存在,T和* T之間的區別是什麼,我唯一可以想到的是* T是指向T的指針,指針的方法與常規方法相比,這是什麼意思? – user3505400

+0

我讀過關於何時應該使用T函數的其他文章,何時應該使用* T函數,他們都告訴我,如果你想修改接收機本身,那麼你應該使用* T,否則你應該使用T,但是在這個那麼,我將如何使用上述考慮來解釋是否應該使用T或* T方法? – user3505400

+0

@ user3505400:當T被聲明時,'* T'被隱含地聲明爲指向'T'的指針,所以它確實存在。是的,區別主要在於您是否可以修改接收器。那麼爲什麼不去只是把指針指向接口中的值呢?這是因爲(afaIk)當你將一個值傳遞給函數時,'a:= struct {42}; Foo(a)',你應該能夠確保'a'不會被改變。 – ANisus