在Go中将函数转换为另一种类型(函数转换)

use*_*400 4 types function type-conversion go

我最近了解到,在net/http包装中,有一种使用模式让我最困惑.它是功能类型转换.它是这样的:

(function a) ->convert to-> (type t)
(type t) ->implentments-> (interface i)
Run Code Online (Sandbox Code Playgroud)

因此,如果有一个以接口i作为参数的函数,它将调用函数a,这是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)
Run Code Online (Sandbox Code Playgroud)

类型aaa有方法eat,相同的函数名和参数签名,符合接口规则,但为什么会出错呢?接收器是否重要?

另一个问题是只有一个函数和类型,不包括接口,代码如下:

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)
Run Code Online (Sandbox Code Playgroud)

首先,是op一个匿名函数,不管错误是什么?

其次,我删除星号后效果很好,但为什么呢?op是类型的实例aaa,接收器是op,op代表功能狗()?http包使用f(w,r)相同的方式,但有点难以理解.是op类型,实例还是匿名函数?

看起来我对功能转换的理解是不对的,但是我也检查过Google上的很多帖子,没有一个能教我如何思考并正确使用它.谢谢你!

ANi*_*sus 9

问题1:

在Go中,对于类型T(在您的情况下类似于aaa),T并且*T具有不同的方法集.

因此,类型T的值只能访问方法:

func(t T)Foo() { ... }
Run Code Online (Sandbox Code Playgroud)

虽然类型*T的值可以访问这两种方法:

func(t T)Foo() { ... }
func(t *T)Bar() { ... }
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您有两种选择.要么声明eat方法aaa而不是od *aaa:

func (op aaa) eat() {
    op()
}
Run Code Online (Sandbox Code Playgroud)

或者您将指针传递bfeelsGood:

feelsGood(&b)
Run Code Online (Sandbox Code Playgroud)

问题2:

是的,这个问题与第一个问题有关.但在这种情况下,您可以访问该方法,因为obj.eat()它将是简短的(&obj).eat().

这里的问题是你不能在函数指针(op*aaa)上调用函数.您可以选择创建方法aaa而不是*aaa:

func (op aaa) eat() {
    op()
}
Run Code Online (Sandbox Code Playgroud)

或者op在值上调用函数而不是指针:

func (op *aaa) eat() {
    (*op)()
}
Run Code Online (Sandbox Code Playgroud)