如何在 Go 中正确实例化并返回通用接口?

问题描述 投票:0回答:1

我正在开发一个 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 generics interface mapper
1个回答
0
投票

您可以转换返回值(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
    }
}

也就是说,您应该“接受接口,返回结构”,并且通常泛型和接口的工作方式与具有继承的语言略有不同。您没有提到您想要实现的目标,所以我无法建议更好的方法来完成您想要的事情。

© www.soinside.com 2019 - 2024. All rights reserved.