我正在try 使用泛型来实现接口Interface.它有一个接受另一个接口作为参数的方法:

type SubInterface interface {
    SendResponse(string)
}

type Interface interface {
    Subscribe(SubInterface)
}

我想出了这些接口的以下通用版本:

type GenericSubInterface[T any] interface {
    SendResponse(T)
}

type GenericInterface[Res any] interface {
    Subscribe(GenericSubInterface[Res])
}

我希望GenericInterface[string]可以赋值给Interface,但不知何故并不是这样.

var a Interface
var b GenericInterface[string]

//  cannot use b (variable of type GenericInterface[string]) as Interface value in assignment: GenericInterface[string] does not implement Interface (wrong type for method Subscribe)
//      have Subscribe(GenericSubInterface[string])
//      want Subscribe(SubInterface)
a = b

创建Interface的通用实现也不起作用:

type GenericImplementation[Res any] struct {
}

func (i *GenericImplementation[Res])Subscribe(ss GenericSubInterface[Res]) {
    var msg Res
    ss.SendResponse(msg)
}
//  cannot use &GenericImplementation[string]{} (value of type *GenericImplementation[string]) as Interface value in variable declaration: *GenericImplementation[string] does not implement Interface (wrong type for method Subscribe)
//      have Subscribe(GenericSubInterface[string])
//      want Subscribe(SubInterface)
var c Interface = &GenericImplementation[string]{}

在我看来奇怪的是,子接口可以相互分配:

var d SubInterface
var e GenericSubInterface[string]

// works fine
d = e

这个问题似乎只有在接口以某种方式嵌套时才会发生.有没有办法解决这个问题,我可以使用string以外的类型的泛型来实现Interface

Full playground example

推荐答案

首先,读Go interface: interface not implemented even though it is.@colm.anseo答案的第一句话就已经概括了这个问题:

签名不一样.参数类型不同

然后读How to implement generic interfaces?.类型SubInterface的值可以赋值给GenericSubInterface中的a particular instantiation个,即GenericSubInterface[string]个,因为这些方法最终是相同的-SendResponse(string).

Interface不能赋给GenericInterface[string],因为方法最终是not identical.错误消息是Eloquent 的,因为它得到:

have Subscribe(GenericSubInterface[string])
want Subscribe(SubInterface)

您可以使用接口的泛型版本,但方法必须准确实现.因此,您必须使函数AcceptInterface也成为通用函数:

func AcceptInterface[T any](a GenericInterface[T]) {
}

func main() {
    var b GenericInterface[string]
    AcceptInterface(b)
}

Go相关问答推荐

为什么在GO中打印变量会导致堆栈溢出?

macOS上GoLand 2023.3.4中的代码导航

map 中的多个函数类型,Golang

创建使用逗号而不是加号分隔OU的CSR

如何使用工作区方法扩展克隆的Golang库

错误&对象已被Golang在K8s操作符上修改

确定果朗CSV行中的字节数

Go 中带有回调的 MiniDumpWriteDump

htmx 表单 + gin 无法正确读取请求正文

带有前导零的整数参数被 flag.IntVar 解析为八进制

Golang:如何在不转义每个动作的情况下呈现模板的模板?

由于 main.go 文件中的本地包导入导致构建 docker 容器时出错

Go http.FileServer 给出意外的 404 错误

具有未导出字段的 struct 类型之间的转换

golang pic.ShowImage 为什么它不生成图像而是向我发送base64值

处理程序后访问 HTTP 请求上下文

对所有标志进行 ORing 的简短方法

如何从 tinygo webassembly 目标返回对象

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

如何在 Go 中使用 RSA 密钥加密和解密纯文本?