当实现具有通用类型的参数/返回值的函数时,Go 中的接口如何工作?

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

我是 Go 新手,对接口在实现时如何工作感到有点困惑,尤其是 wrt。有参数的函数。假设我有一个带有函数

foo
的接口,它接受一个接口:

type I interface {
  foo(x interface{})
}

还有类型

A
B
如下:

type A struct {
  // stuff
}
type B struct {
  // stuff
}

(a *A) foo(b B) {
 // do something
}

既然在这个例子中,

A
有方法
foo
,那么即使使用
I
的规范作为参数而不是通用接口,它是否被认为已经实现了
B
?我对函数的返回类型也有同样的问题。

如果没有,如何设计一个接口来允许更通用的参数/返回类型以及实现它的结构来指定类型?

go struct types interface polymorphism
1个回答
0
投票

A有方法

foo
,是否认为已经实现了
I

没有。

接口

I
由一个方法
foo
组成,该方法接受
interface{}
参数。 这并不意味着它接受任何类型的单个参数。 这意味着它接受一个使用空方法集实现特定接口的参数。 对于此类参数采用

any

类型可能会帮助你理解区别(从 go 1.18 开始支持):

type I interface {
  foo(x any)
}

为了满足此接口,类型必须实现一个方法 
foo

接受

any
参数;仅使用单个参数实现
foo
方法是不够的,其中该参数的类型无关。
您似乎正在寻找一个

generic

接口(泛型也在go 1.18中引入): type I[T any] interface { foo(T) }

通用接口 
T

上的类型参数

I
具有
any
约束,这意味着可以提供任何类型。
如果类型

A

实现了接受

foo
类型参数的
B
方法,那么这将被视为实现了接口
I[B]
:
type I[T any] interface {
    foo(B)
}

type A struct{}

type B struct{}

func (A) foo(B) { log.Println("it works") }

func main() {
    var a any = A{}

    c := a.(I[B])
    c.foo(B{})
}

游乐场

a

使用

A
类型的值进行初始化,但
a
本身是
any
类型,因此不能直接用于调用
foo()
方法。

c

通过将

a
强制到接口
I[B]
来初始化,从而允许调用
foo(B)
方法。
    

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