Golang中如何为any类型传递更具体的类型参数

Golang中如何为any类型传递更具体的类型参数 考虑以下代码片段(playground

package main

import "fmt"

type Foo struct{}

func foo() (Foo, error) {
	return Foo{}, nil
}

type Bar struct{}

func bar() (Bar, error) {
	return Bar{}, nil
}

func Wrap(fn func() (any, error)) func() string {
	return func() string {
		d, err := fn()
		if err != nil {
			return err.Error()
		} else {
			return fmt.Sprint(d)
		}
	}
}

func main() {
	_ = Wrap(foo)
	_ = Wrap(bar)
}

尝试编译此代码会产生以下错误:

./prog.go:29:11: cannot use foo (value of type func() (Foo, error)) as func() (any, error) value in argument to Wrap
./prog.go:30:11: cannot use bar (value of type func() (Bar, error)) as func() (any, error) value in argument to Wrap

有没有办法修改 Wrap 的签名来允许这种情况?目前的一个解决方法是:

func main() {
	_ = Wrap(func() (any, error) { return foo() })
}

但这相当繁琐。


更多关于Golang中如何为any类型传递更具体的类型参数的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

感谢您的建议,但实际上有很多类型会让这再次变得繁琐。由于 Wrap 的实现实际上可以与 any 对象一起工作,因此没有必要人为地限制它。

更多关于Golang中如何为any类型传递更具体的类型参数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果你使用泛型,可以创建一个比 any 限制性更强的泛型类型。例如,

func Wrap[T Foo | Bar](fn func() (T, error)) func() string {
...
}

你可以使用泛型。

func Wrap(fn func() (any, error)) func() string {

替换为

func Wrap[T any](fn func() (T, error)) func() string {

在Go中,any类型与具体类型之间的函数签名不兼容,但可以通过泛型来解决这个问题。以下是修改后的代码:

package main

import "fmt"

type Foo struct{}

func foo() (Foo, error) {
	return Foo{}, nil
}

type Bar struct{}

func bar() (Bar, error) {
	return Bar{}, nil
}

// 使用泛型类型参数T
func Wrap[T any](fn func() (T, error)) func() string {
	return func() string {
		d, err := fn()
		if err != nil {
			return err.Error()
		} else {
			return fmt.Sprint(d)
		}
	}
}

func main() {
	// 现在可以直接传递foo和bar函数
	wrappedFoo := Wrap(foo)
	wrappedBar := Wrap(bar)
	
	fmt.Println(wrappedFoo()) // 输出: {}
	fmt.Println(wrappedBar()) // 输出: {}
}

或者,如果你需要保持Wrap函数接受func() (any, error)签名,但让调用更简洁,可以使用辅助函数:

func WrapAny[T any](fn func() (T, error)) func() string {
	return Wrap(func() (any, error) {
		return fn()
	})
}

func main() {
	// 使用辅助函数
	_ = WrapAny(foo)
	_ = WrapAny(bar)
}

泛型解决方案是最直接的方法,它允许Wrap函数接受返回任意具体类型的函数,同时保持类型安全。编译器会自动推断类型参数T,因此调用时不需要显式指定类型。

回到顶部