Basic + Slice + Map 类型兼容泛型?

有没有办法创建一个通用函数,在传递映射或切片类型与基本类型时可以调整其操作?


目标

创建一个具有灵活返回类型的切片读取函数生成器:


func ValueReader[T <probably something fancy>](i int) func ([]ProtoConvertable) T {

    return func (row []ProtoConvertable) T {

        return ...

    }

}


row := []ProtoConvertable{

    &Data[int]{Value: 333},

    &ListData{Values: []ProtoConvertable{

        &Data[string]{Value: "hello"},

        &Data[string]{Value: "world"},

    }},

    MapData{Values: map[ProtoConvertable]ProtoConvertable{

        &Data[int]{Value: 22}: &Data[string]{Value: "world"},

        &Data[int]{Value: 11}: &Data[string]{Value: "hello"},

    }},

}


dataReader := ValueReader[int](0) // A function that converts the first element to an int

listDataReader := ValueReader[[]string](1) // A function that converts the second element to a slice

mapDataReader := ValueReader[map[int]string](2) // A function that converts the third element to a map


data := dataReader(row) // 333

listData := listDataReader(row) // []string{"hello", "world"}

mapData := mapDataReader(row) // map[int]string{11: "hello", 22: "world"}

类型

type ValueType interface {

    int | string

}


type ProtoConvertable interface {

    ToProto() *pb.GenericMessage

}


type Data[T ValueType] struct {

    Value T

}


func (d *Data) ToProto() *pb.GenericMessage{

    ...

}


type ListData struct {

    Values []ProtoConvertable

}


func (d *ListData) ToProto() *pb.GenericMessage {

    ...

}


type MapData struct {

    Values map[ProtoConvertable]ProtoConvertable

}


func (d *MapData) ToProto() *pb.GenericMessage {

    ...

}

当前解决方案

func ValueReader[T ValueType](i int) func([]ProtoConvertable) T {

    return func(row []ProtoConvertable) T {

        return row[i].(*Data[T]).Value

    }

}


func ListValueReader[T ValueType](i int) func([]ProtoConvertable) []T {

    return func(row []ProtoConvertable) []T {

        vs := row[i].(*ListData).Values

        res := make([]T, len(vs))

        for i, v := range vs {

            res[i] = v.(*Data[T]).Value

        }

        return res

    }

}



注意:所有这些代码都是一个更复杂的库的未经测试的简化。它可能需要一些调整才能真正工作。


摇曳的蔷薇
浏览 108回答 1
1回答

智慧大石

<probably something fancy>不存在。主要问题是您想要建模一个匹配基值和两个复合类型的类型参数,其中一个是您想要同时捕获K和的映射类型V。即使它存在,它的主体ValueReader也会是一个类型开关,T以返回每个专门的阅读器函数,因此您现有的涉及少量代码重复的解决方案总体上似乎只是一个更好的策略。我的建议是当对不同具体类型的操作T完全相同时使用泛型。您可以在以下位置阅读更多信息:https ://go.dev/blog/when-generics
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go