2014-04-07 55 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