简体   繁体   English

golang函数类型继承?

[英]golang function type inheritance?

Consider this example in Go language:考虑这个 Go 语言的例子:

type I interface {
    get() string
}

type S struct {}
func (s *S) get() string {
    return "here!"
}
var sSupplier = func() *S {
    return &S{}
}

func foo(supplier func () I) {
    i := supplier()
    println(i)
}

func main() {
    foo(sSupplier) // compile error, type mismatch
}

Type S inherit interface I . S继承接口I But apparently type func () *S does not inherit func () I , so I cannot call foo with sSupplier in place of the supplier function.但显然类型func () *S没有继承func () I ,所以我不能用sSupplier调用foo代替supplier函数。 Is there a way to fix it without forcing sSupplier to return type I ?有没有办法在不强制sSupplier返回类型I情况下修复它?

In java you can use generics to do something like <T extends I> void foo(Supplier<T> supplier) {...} then call foo(sSupplier);在 Java 中,您可以使用泛型来执行类似<T extends I> void foo(Supplier<T> supplier) {...} foo(sSupplier); <T extends I> void foo(Supplier<T> supplier) {...}然后调用foo(sSupplier); with Supplier<S> sSupplier type.使用Supplier<S> sSupplier类型。 I'm not sure if similar approach is possible in go?我不确定在 go 中是否可以使用类似的方法?

If you think for a bit about what generics do for you, they are really a way to ask the compiler to compile, on the spot, an anonymous wrapper function or lambda or whatever is needed to map from some concrete type.如果您稍微考虑一下泛型为您做什么,它们实际上是一种要求编译器在现场编译匿名包装函数或 lambda 或从某些具体类型映射所需的任何内容的方法。 That is, given something like (I'll use C++ syntax here rather than Java as I'm much more familiar with C++):也就是说,给定类似的东西(我将在这里使用 C++ 语法而不是 Java,因为我更熟悉 C++):

template<T>
void f(T obj) {
    // do stuff with the object
}

you're telling the compiler that when it sees f(int_value) it should build a function f that takes an int , and when it sees f(struct S) it should build a function f that takes a struct S , and so on.你告诉编译器,当它看到f(int_value)它应该构建一个接受int的函数f ,当它看到f(struct S)它应该构建一个接受struct S的函数f ,依此类推。 (This is a bit more natural in Java than it is in C++'s C underpinnings since Java does the whole argument-matching thing to decide which of these various f functions to call.) (这在 Java 中比在 C++ 的 C 基础中更自然一些,因为 Java 做了整个参数匹配的事情来决定调用这些各种f函数中的哪一个。)

In effect, instead of writing the actual function, you write a template —hence the C++ keyword—that the compiler can use to, at compile time, produce the function you really wanted.实际上,不是编写实际的函数,而是编写一个模板(因此是 C++ 关键字),编译器可以使用它在编译时生成您真正想要的函数。 Since Go lacks generics, it lacks this sort of template-expansion trick.由于 Go 缺少泛型,因此它缺少这种模板扩展技巧。

That leaves you with several obvious alternatives, though.不过,这给您留下了几个明显的选择。 One is exemplified by go:generate (see, eg, Explain go generate in this example ).一个例子是go:generate (参见,例如,在这个例子中解释 go generate )。 In this particularly simple case, though, you can just write the expansion yourself in line:但是,在这种特别简单的情况下,您可以自己编写扩展:

foo(func() I { return sSupplier() })

See a more complete example on the Go playground .Go playground上查看更完整的示例。 I replacd your println(i) with fmt.Printf("%#v\\n", i) to print the interface object's value in a slightly more useful form.我用fmt.Printf("%#v\\n", i)替换你的println(i)以稍微更有用的形式打印接口对象的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM