我正在使用GO泛型创建数据 struct .

用例是编写一个REDUTE函数,该函数获取已定义类型的片,将REDUTE函数应用于该片的每个元素,并返回已定义类型的值.

type MyType[T any] struct{
    I T
}

// I want to write something like this
func (m *MyType[[]T]) Reduce(init T, fnReduce func(T, T)T) (*MyType[T]) {
    acc := init
    for _, v := range m.I {
        acc = fnReduce(acc, v)
    }
    return &MyType[T]{I : acc}

}

GO编译器不允许为接收方提供类型参数,如下所示: m *MyType[[]T]

有什么办法可以解决这个问题?

推荐答案

如果你想在一个切片上有一个方法来减少它,定义MyStructT的切片:

type MyType[T any] []T

func (m MyType[T]) Reduce(init T, fnReduce func(acc, elem T) (result T)) T {
    res := init
    for _, v := range m {
        res = fnReduce(res, v)
    }
    return res
}

这里有一个关于Playground的例子.


如果您需要能够将切片本身之外的其他字段添加到MyStruct,则具有包含切片的字段的 struct 也是一个选项.(New func用于从包外部填充私有切片字段.

func NewMyType[T any](sl []T) MyType[T] {
    return MyType[T]{sl: sl}
}

type MyType[T any] struct {
    sl []T
}

func (m MyType[T]) Reduce(init T, fnReduce func(acc, elem T) (result T)) T {
    res := init
    for _, v := range m.sl {
        res = fnReduce(res, v)
    }
    return res
}

关于 comments 中所述的问题:

  1. 第一个 idea 是,每当确定需要减少数据时,就调用Reduced函数.如果有一个地方我们知道数据是Slice类型的,那么这就行得通.如果从来不是这样(所有代码都是通用的),那么看看选项2).
func reduce[T any](sl []T, init T, fnReduce func(acc, elem T) (result T)) T {
    res := init
    for _, v := range sl {
        res = fnReduce(res, v)
    }
    return res 
}
  1. 第二个 idea 是拥有一个针对不同数据类型不同实现的老式接口.
type MyI[T any] interface {
    Reduce(init T, reduce func(acc, elem T) (result T)) T
}

type MySliceType[T any] struct {
    data []T
}

func (m MySliceType[T]) Reduce(init T, reduce func(acc, elem T) T) T {
    res := init
    for _, v := range m.data {
        res = reduce(res, v)
    }
    return res
}

type MyType[T any] struct {
    data T
}

func (m MyType[T]) Reduce( T,  func(acc, elem T) T) T {
    return m.data
}

我们这里有一个常见的Reduce函数,以防我们没有切片,它只返回m.data.如果我们有一个切片,它实际上应用了REDUTE函数.

(这个例子没有太多意义,但我希望这个 idea 能被理解.)

Go相关问答推荐

读取JSON数据并在网页上显示

获取作为类型参数传递给方法接收方中的类型参数的切片的基础类型

GoLang:无法发送带有附件的邮箱

Golang SDK for DynamoDB:ReturnValuesOnConditionCheckFailure在条件chcek失败发生时不返回条件的详细信息

提供的client_secret与此帐户上任何关联的SetupIntent都不匹配

go测试10m后如何避免超时

Go 1.20 中如何计算连接错误?

使用Cookie身份验证的Gorilla Golang Websocket优化

这是实现超时的常见方法,为什么 time.After 不起作用

Golang prometheus:有没有办法衡量出站请求的指标?

linter 警告:返回值被忽略

对 CSV 进行单元测试失败

在反向 GORM 中创建查询有一个关系

Golang Gin 绑定请求正文 XML 到 Slice

go:识别重新定义标志的包

为什么import和ImportSpec之间可以出现多行注释,而PackageName和ImportPath之间不能出现?

在 Go 中将指针传递给函数的正确方法是什么,以便我可以读取和/或修改指针表示的值?

如何在测试中传递用户名和密码等参数

即使没有竞争条件也没有得到任何输出

在 Go 中表达函数的更好方法( struct 方法)