Go语言 如何使用泛型将接口传递给指定的类型

yhxst69z  于 2023-02-17  发布在  Go
关注(0)|答案(1)|浏览(170)

有一个接口声明和许多实现它的结构

type DataInterface interface {
    Get(string) string
}

type DataA struct {
    d map[string]string
}

func (d *DataA) Get(key string) string {
    return d.d[key]
}

func (d *DataA) GetId() string {
    return d.Get("id")
}

type DataB struct {
    d map[string]string
}

func (d *DataB) Get(key string) string {
    return d.d[key]
}

func (d *DataB) GetFile() string {
    return d.Get("file")
}

type DataC...

还包括DataC,D,E...
我将把这些DataX结构体示例存储到type DataSlice []DataInterface
现在,如果我想得到DataX,我可以这样做:

type DataSlice []DataInterface
func (d DataSlice) GetA() []*DataA {
    var ret []*DataA
    for _, di := range d {
        if v, ok := di.(*DataA); ok {
            ret = append(ret, v)
        }
    }
    return ret
}

func (d DataSlice) GetB() []*DataB {
    var ret []*DataB
    for _, di := range d {
        if v, ok := di.(*DataB); ok {
            ret = append(ret, v)
        }
    }
    return ret
}

func (d DataSlice) GetC() .....

显然这里有很多重复的代码:

var ret []*DataX
for _, di := range d {
    if v, ok := di.(*DataX); ok {
        ret = append(ret, v)
    }
}

我想我可以用泛型来解决这个问题,然后我定义了这个函数:

func GetDataX[T any] (d DataInterface) *T {
    return d.(*T)
}

但出现错误:Impossible type assertion: '*T' does not implement 'DataInterface
所以,我想知道这个方法真的不可能吗?还是可以用另一种方法来完成?

xxe27gdn

xxe27gdn1#

您应该能够使用以下代码处理您的需求:

package main

import "fmt"

// interface
type DataInterface interface {
    Get(string) string
}

// struct implementing the interface
type DataA struct {
    d map[string]string
}

func (d DataA) Get(key string) string {
    return d.d[key]
}

type DataB struct {
    d map[string]string
}

func (d DataB) Get(key string) string {
    return d.d[key]
}

type DataSlice []DataInterface

func GetDataX[T any](d DataInterface) T {
    return d.(T)
}

func main() {
    a := DataA{map[string]string{"a": "1"}}
    b := DataB{map[string]string{"b": "2"}}

    ds := DataSlice{a, b}

    for _, v := range ds {
        if value, ok := v.(DataA); ok {
            fmt.Printf("A\t%q\n", GetDataX[DataA](value))
            continue
        }

        if value, ok := v.(DataB); ok {
            fmt.Printf("B\t%q\n", GetDataX[DataB](value))
            continue
        }

        // add unknown type handling logic here
    }
}

首先,我简化了代码,只考虑DataADataB结构体。然后,我将指针接收器改为值接收器,因为你不打算改变传递给方法的实际示例的状态。多亏了这个改变,GetDataX工作成功,你能够获得所有类似结构体的信息。
让我知道如果这解决了你的问题或者如果你需要其他的东西,谢谢!

相关问题