定义一个返回任意类型的命名函数类型。

huangapple go评论82阅读模式
英文:

Defining a named function type that returns any type

问题

我想定义一个函数类型(在C#中称为委托),其返回值可以是任何类型(在编译时未知),在阅读Go文档后,我发现当前版本的语言不支持泛型。

在StackOverflow上搜索后,我看到一篇帖子建议将返回类型设置为interface{},这意味着该函数可以返回任何类型。然后我编写了以下代码来测试它的工作原理:

type Consumer func() interface {}

func TestConsumer() Consumer {
    return func() string {
         return "ok"
    }
}

但是我得到了以下错误:

无法将函数文字(类型为func() string)用作返回参数中的Consumer类型

而当我将Consumer的返回类型更改为string时,它可以正常工作。

问题是我做错了什么,如何编写一个可以返回任何类型的函数类型(委托)并将实际函数分配给它?

英文:

I would like to define a function type (what we call delegate in C#) whose return value can be anything (is unknown at compile type) and after reading Go docs I found that the current version of the language does not support generics.

After searching StackOverflow I came across a post suggesting that the return type can be set as interface{} which implies that any type can be returned by that function. Then I wrote the following code to test how it works:

type Consumer func() interface {}

func TestConsumer() Consumer {
    return func() string {
         return "ok"
    }
}

But I got the following error

> cannot use func literal (type func() string) as type Consumer in return argument

This is while when I change the return type of Consumer to string, it works without any problem.

The question is what is that I am doing wrong and how can I achieve writing a function type (delegate) that can return anything and assign an actual functions to that?

答案1

得分: 1

问题在于函数类型 func() string 不符合函数类型 func() interface{}

原因是函数类型 func() interface{} 表示一个显式返回 interface{} 类型值的函数,而 string 类型可以轻松地转换为 interface{},但是整体的 函数签名不同的。

正确的代码应该是:

type Consumer func() interface {}

func TestConsumer() Consumer {
    return func() interface{} {
         return "ok"
    }
}

字符串会隐式转换为 interface{} 类型,函数签名相同。

英文:

The issue is that the function type func() string does not conform to the function type func() interface{}.

The reason for this is because the function type func() interface{} means a function that explicitly returns a value of type interface{}, and while a string can be easily casted to an interface{}, the overall function signatures are not the same.

The correct code would be:

type Consumer func() interface {}

func TestConsumer() Consumer {
    return func() interface{} {
         return "ok"
    }
}

The string gets implicity casted to the interface{} type, and the function signatures are the same.

答案2

得分: 1

如果您可以使用Go 1.18,可以使用类型参数来定义自己的通用命名函数类型。然后,您可以在其他通用函数中使用它,并在需要时使用类型参数进行实例化,或者使用具体类型进行实例化:

假设一个返回T的函数被称为"producer":

type Producer[T any] func() T

// 使用具体类型进行实例化
func TestProducer() Producer[string] {
    return func() string {
         return "ok"
    }
}

// 使用类型参数进行实例化
func TestProducer[T any]() Producer[T] {
    return func() T {
        return *new(T)
    }
}

在后一种情况下,您将需要实例化TestProducer —— 一般规则是,在某个时刻,类型参数必须在编译时已知。

func main() {
    fn := TestProducer[string]()
    foo := fn()
    fmt.Println(foo) // foo 是空字符串

    fn2 := TestProducer[uint64]()
    bar := fn2()
    fmt.Println(bar) // bar 是 0
}

Playground: https://go.dev/play/p/HDmgV_vu7MN

英文:

If you can use Go 1.18, use type parameters to define your own generic named function type. You can then use it in other generic functions and instantiate it with a type parameter, or instantiate it with concrete types when needed:

<sup>let's say that a function that returns T is called a "producer" though</sup>

type Producer[T any] func() T

// instantiate with concrete type
func TestProducer() Producer[string] {
    return func() string {
         return &quot;ok&quot;
    }
}

// instantiate with type parameter
func TestProducer[T any]() Producer[T] {
    return func() T {
        return *new(T)
    }
}

In the latter case, you'll have to instantiate TestProducer — the general rule being, at some point the type parameters must be known at compile time.

func main() {
    fn := TestProducer[string]()
    foo := fn()
    fmt.Println(foo) // foo is the empty string

    fn2 := TestProducer[uint64]()
    bar := fn2()
    fmt.Println(bar) // bar is 0
}

Playground: https://go.dev/play/p/HDmgV_vu7MN

答案3

得分: -1

func TestConsumer() interface{} {
    return func() string {
         return "ok"
    }
}

请尝试使用这个代码。

英文:
func TestConsumer() interface{} {
    return func() string {
         return &quot;ok&quot;
    }
}

Please try with this one

huangapple
  • 本文由 发表于 2022年2月23日 16:19:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/71233405.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定