如何像在 Java 中一样在 Go 中传递方法引用?

Jac*_*cob 7 generics go

我正在将我的应用程序从 Java 重写为 Go,我知道这些语言以及范式完全不同,但我仍然设法转换几乎所有内容。

不幸的是,我无法将通用函数作为参数传递给另一个函数。在 Java 中它看起来像这样:

我有一个界面:

public interface Parser<T> {
    public T parse(String line);
}
Run Code Online (Sandbox Code Playgroud)

fetch然后我在通用方法中使用这个接口

public static <T> List<T> fetch(Parser<T> parser) {
    ...
    parser.parse(someLine);
    ...
    return the list of generic types
}
Run Code Online (Sandbox Code Playgroud)

那么解析器方法如下所示:

class Parser{
    static Foo ParseFoo(String line){
        ...
        some custom parsing
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我这样使用它:

List<Foo> list = fetch(Parser::ParseFoo);
Run Code Online (Sandbox Code Playgroud)

我如何在 Go 中实现这一目标?

我尝试过声明通用接口、通用函数,但我无法理解这一点。

眠りネ*_*ネロク 6

等效的通用Parser接口如下所示:

\n
type Parser[T any] interface {\n    Parse(line string) T\n}\n
Run Code Online (Sandbox Code Playgroud)\n

任何具有Parse(string) S方法的类型都会隐式满足Parser[S]接口。例如,以下类型Foo满足Parser[int]

\n
type Foo struct{}\n\nfunc (f Foo) Parse(string) int {\n    return 0\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后,使用通用Parser接口,您可以实现通用Fetch功能:

\n
func Fetch[T any](parser Parser[T]) []T {\n    panic("not implemented")\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

传递满足接口的值

\n

那么,在 Go 中,您将如何执行相当于传递 Java静态方法的操作,如下ParseFoo()所示?

\n
class Parser {\n    static Foo ParseFoo(String line) {\n      ...\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在 Go 中,没有静态方法。函数可以附加到类型,在这种情况下它们就成为方法。因此,对于 Java 中的静态方法的情况,通常会在 Go 中得到非方法函数独立函数

\n
func ParseFoo(line string) Foo {\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

为了使这个函数满足Parser[Foo]接口,可以定义如下ParserFunc适配器:

\n
type ParserFunc[T any] func(string) T\n\nfunc (f ParserFunc[T]) Parse(line string) T {\n    return f(line)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这样,从不ParseFoo附加到任何类型 \xe2\x80\x93 的独立函数 \xe2\x80\x93 中,您可以创建一个值ParserFunc[Foo],它确实满足Parser[Foo],并且只会在调用ParseFooParse方法时调用:

\n
f := ParserFunc[Foo](ParseFoo)\n
Run Code Online (Sandbox Code Playgroud)\n

最后,您可以将此f值传递给fetchsince fsatisfies Parser[Foo]

\n
fetch[Foo](f)\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,您需要指定类型参数Foo,因为fetch编译器无法推断它。

\n
\n

如果您确实需要一个方法(即,像 Java 中的非静态/实例方法),那么您可能需要查看方法值。该过程将与此处公开的过程类似。

\n