Go:“嵌入类型不能是类型参数”

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

我正在使用 Go 泛型在“请求-响应”风格的 goroutine 上编写一个类型安全的包装器,并偶然发现了一个编译错误:

type WorkerContext[In any, Out any] interface {
    Process(In) (Out, bool)
    Destroy()
}

type Worker[In any, Out any] struct {
    context WorkerContext[In, Out]
    in      chan In
    out     chan struct{Out; bool}
}

这里,一个 goroutine 由一个

Worker
实例表示,在 goroutine 中执行以处理请求的用户代码由
WorkerContext
接口表示(该接口可能持有任意外部资源,例如一个子进程Goroutine 正在与之通信。

这里的想法是,

WorkerContext.Process()
函数返回处理请求的结果,以及指示外部资源是否可以接受更多请求的标志。这两个值都通过通道传输回请求线程。在那里,该标志用于决定是否将工作线程(及其关联的 goroutine 和上下文)放回到工作线程池中或销毁它(在下一个请求出现时创建一个新的)。

但是,我似乎无法声明这样的通道:

src/taskpool/taskpool.go:24:22: embedded field type cannot be a (pointer to a) type parameter

为什么会这样呢?这种限制感觉有点武断,我在这里想做的事情的惯用方法是什么?

go generics
1个回答
0
投票

此时实现此操作的唯一方法是使用显式字段名称:

type Worker[In any, Out any] struct {
    context WorkerContext[In, Out]
    in      chan In
    out     chan struct {
        Out Out
        Ok  bool
    }
}

它还可以避免嵌入预先声明的标识符(例如

bool
)时出现意外。在您原来的示例中,
Out
将被导出,而
bool
则不会。此处使用显式字段名称有助于阐明代码的用途。导出字段。

关于编译器为何拒绝这一点的最新讨论(尽管原始泛型提案暗示相反)可以在这里找到:cmd/compile:嵌入字段类型不能是(指向)类型参数

罗伯特·格里塞默 于 2021 年 10 月 19 日说

我们初步得出结论,由于方法升级的问题,最初可能不允许嵌入类型参数。指向类型参数的指针也会出现同样的问题。但也许我们终究可以允许这种情况发生。

会重新考虑。

然后又十天后

我们已经再次讨论过这一点,并且我们不会在 1.18 中更改这一点。理由:

  • 关于这种嵌入字段的类型,还存在一些悬而未决的问题。也考虑一下这种情况:
func f[P constraint]() {
   type S struct{
      P // <<< should this be permitted?
   }
   ...
}
  • 关于方法推广存在一些悬而未决的问题。
  • 我们可以稍后添加它,但如果我们犯了错误,我们将无法删除该功能。
  • 实施已受到限制;在代码冻结之前进行此类更改是有风险的。

仿制药提案仍然描述了这种可能性,这只是一个疏忽。最终,规范(正在进行中)将成为最终的指导文件。

结束。一旦我们获得了更多关于类型参数的经验,我们就可以重新考虑这个建议。

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