pmeier
(Philip Meier)
April 1, 2025, 10:00am
1
Consider the following snippet (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)
}
Trying to compile this yields the following error:
./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
Any way to change the signature of Wrap to allow for this? A workaround currently is to do
func main() {
_ = Wrap(func() (any, error) { return foo() })
}
but that is quite cumbersome.
pekim
(Mike D Pilsbury)
April 1, 2025, 10:44am
2
You could use generics.
Replace
func Wrap(fn func() (any, error)) func() string {
with
func Wrap[T any](fn func() (T, error)) func() string {
3 Likes
blogscot
(Iain Diamond)
April 1, 2025, 10:53am
3
If you’re using generics you could create a generic type more restrictive than any. For example,
func Wrap[T Foo | Bar](fn func() (T, error)) func() string {
...
}
1 Like
pmeier
(Philip Meier)
April 1, 2025, 11:33am
4
Thanks for the suggestion, but there are actually quite a few types that would make this cumbersome again. Since the implementation of Wrap actually does work with any object, there is no need to restrict it artificially.
pmeier:
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)
}
Trying to compile this yields the following error:
./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
Any way to change the signature of Wrap to allow for this? A workaround currently is to do
func main() {
_ = Wrap(func() (any, error) { return foo() })
}
but that is quite cumbersome.
Yeah, this happens because Go doesn’t allow implicit conversion of concrete return types to any. You’ll need to explicitly wrap the function call.
One way to adjust Wrap is to use generics:
func Wrap[T any](fn func() (T, error)) func() string {
return func() string {
d, err := fn()
if err != nil {
return err.Error()
}
return fmt.Sprint(d)
}
}
This should let you use Wrap(foo) and Wrap(bar) without needing the extra wrapper function.
system
(system)
Closed
July 4, 2025, 5:30pm
6
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.