我正在开发一个 Go 项目,我需要创建一个可以由不同结构实现的通用接口。我还想要一个函数,根据提供的输入类型返回此接口的实例。但是,我遇到了类型约束和泛型类型实例化的问题。这是我的代码:
package main
import "fmt"
// Define TestA and TestB types
type TestA struct {
Value string
}
type TestB struct {
Number int
}
type TestC struct {
Value string
}
type TestD struct {
Number int
}
type Mapper[B TestA | TestB] interface {
Map() B
}
type AMapper struct{}
func (a AMapper) Map() TestA {
return TestA{Value: "Mapped to TestA"}
}
type BMapper struct{}
func (b BMapper) Map() TestB {
return TestB{Number: 42}
}
func NewBMapper() BMapper {
return BMapper{}
}
func GetMapper[A TestC | TestD, B TestB | TestA](a B) Mapper[B] {
switch any(a).(type) {
case TestB:
return NewBMapper()
default:
return nil
}
}
func main() {
testB := TestB{1}
mapperB := GetMapper[TestC, TestB](testB)
fmt.Println(mapperB.Map())
}
我遇到的错误如下:
./prog.go:45:10: cannot use NewBMapper() (value of type BMapper) as Mapper[B] value in return statement: BMapper does not implement Mapper[B] (wrong type for method Map)
have Map() TestB
want Map() B
如何在这种情况下正确实例化并返回通用接口? 这里还有一个 Playground 链接:https://go.dev/play/p/C9KPQD1fws5
如果这样无法解决,还有其他方法可以实现类似的效果吗?
您可以转换返回值(Go Playground):
func GetMapper[A TestC | TestD, B TestB | TestA](a B) Mapper[B] {
switch any(a).(type) {
case TestB:
if ret, ok := any(NewBMapper()).(Mapper[B]); ok {
return ret
}
panic("logic error")
default:
return nil
}
}
也就是说,您应该“接受接口,返回结构”,并且通常泛型和接口的工作方式与具有继承的语言略有不同。您没有提到您想要实现的目标,所以我无法建议更好的方法来完成您想要的事情。