Go:将变量传递给函数,并返回一个接口

huangapple go评论66阅读模式
英文:

Go: Variable to a function, returning an interface

问题

在Go语言中,为什么我不能将一个返回接口类型的函数赋值给一个变量?

以下是一个最简测试案例:

type DummyInterface interface {
    Method(string) string
}

// Dummy 实现了 DummyInterface 接口
type Dummy struct{}

func (d Dummy) Method(i string) string {
    return i
}

// DummyFunc 返回一个 Dummy 指针(实现了 DummyInterface 接口)
var DummyFunc (func() *Dummy) = func() *Dummy {
    a := Dummy{}
    return &a
}

// DummyInterfaceFunc 声明为返回一个返回实现 DummyInterface 接口的对象的函数 -- 它被设置为 DummyFunc,而 DummyFunc 确实返回一个符合要求的对象
var DummyInterfaceFunc (func() DummyInterface) = DummyFunc

这段代码无法编译通过(Playground 示例在这里),报错信息为:

cannot use DummyFunc (type func() *Dummy) as type func() DummyInterface in assignment

然而,正如你所看到的,*Dummy 确实实现了 DummyInterface 接口。

为什么会这样呢?

英文:

In Go, why can I not have a variable to a function, which returns an interface type?

Here's a minimal test case:

type DummyInterface interface {
    Method(string) string
}

// Dummy implements the DummyInterface interface
type Dummy struct{}

func (d Dummy) Method(i string) string {
	return i
}

// DummyFunc returns a Dummy pointer (which implements the DummyInterface interface)
var DummyFunc (func() *Dummy) = func() *Dummy {
	a := Dummy{}
	return &a
}

// DummyInterfaceFunc is declared as returning function returning an object which implements DummyInterface -- it
// is set to DummyFunc, which does return a conforming object
var DummyInterfaceFunc (func() DummyInterface) = DummyFunc

This fails to compile (Playground example here), stating:

cannot use DummyFunc (type func() *Dummy) as type func() DummyInterface in assignment

Yet, as you can see, a *Dummy does implement DummyInterface.

Why is this?

答案1

得分: 5

因为*DummyDummyInterface不是相同的类型。只有在字面上的情况下,才能将一个对象赋值给它实现的接口类型。如果接口类型出现在类型的参数中(例如函数的返回类型),则无法进行赋值。

请参考赋值规则获取更多信息。

赋值规则

在以下任何情况下,值x都可以分配给类型为T的变量("x可以分配给T"):

  • x的类型与T相同。
  • x的类型V和T具有相同的底层类型,并且V或T中至少有一个不是命名类型。
  • T是接口类型,并且x实现了T。
  • x是双向通道值,T是通道类型,x的类型V和T具有相同的元素类型,并且V或T中至少有一个不是命名类型。
  • x是预声明的标识符nil,T是指针、函数、切片、映射、通道或接口类型。
  • x是可由T类型的值表示的无类型常量。
英文:

Because *Dummy is not the same type as DummyInterface. The rule that you can assign an object to something of an interface type that object implements only applies in that literal case. If the interface type appears in one of the parameters of a type (i.e. the return type of a function), assignment is not possible.

Refer to the assignability rules for more information.

> ## Assignability
>
> A value x is assignable to a variable of type T ("x is assignable to
> T") in any of these cases:
>
> * x's type is identical to T.
> * x's type V and T have identical underlying types and at least one of V or T is not a named type.
> * T is an interface type and x implements T.
> * x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not
> a named type.
> * x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
> * x is an untyped constant representable by a value of type T.

答案2

得分: 1

这与以下概念类似:我可以将 []T 转换为 []interface{} 吗?

基本上,func() *Dummyfunc() DummyInterface 是不同的类型,它们之间无法进行转换。

你需要在整个过程中使用接口,以使函数签名保持一致。

英文:

This is a similar concept to: Can I convert a []T to an []interface{}?

Basically func() *Dummy is a different type from func() DummyInterface, and conversion between them is not possible.

You will need to use the interface throughout to make the function signature the same.

huangapple
  • 本文由 发表于 2014年7月8日 23:51:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/24636305.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定