接口和地址运算符

Interfaces and address operators

我无法理解为什么当 return 类型是接口时可以使用地址运算符

func NewReader() IReader {
    return &Reader{}
}

但是(当然)当 return 类型是结构时就不会了

func NewReader() Reader {
    return &Reader{} // cannot use &Reader literal (type *Reader) as type Reader in return argument
}

后面的函数签名是func MyFuncReader(r IReader)但是reflect.TypeOf(r)*main.Reader

  1. 所以类型 IReader 隐藏了它是指针的事实?
  2. 函数签名 func MyFuncReader(r IReader) 没有告诉我,一个指针或一个值被传递给了函数?

示例

  1. 带接口的完整示例 https://play.golang.org/p/1Db1Jybp0rP
  2. 没有界面的完整示例https://play.golang.org/p/nPtu09yhe0C

如果函数的 return 类型是接口类型,您可以 return 实现该接口的任何值。 Spec: Return statements:

The return value or values may be explicitly listed in the "return" statement. Each expression must be single-valued and assignable to the corresponding element of the function's result type.

在您的第一个示例中,Reader 具有带有 指针接收器 的方法,因此只有指向 Reader(即 *Reader)的指针实现IReader 界面。所以你到return&Reader{}.

如果你的函数有一个 return 类型的具体类型,你必须 return 那个具体类型的值,你不能 return a 的值指向该类型的指针。

当 return 类型是 Reader

func NewReader() Reader {
    return &Reader{} // cannot use &Reader literal (type *Reader) as type Reader in return argument
}

您不能使用指向 Reader 类型的指针来代替 Reader 类型。原因是它们不是同一类型。

当您使用像 IReader 这样的接口作为 return 类型时,如

func NewReader() IReader {
    return &Reader{}
}

它基本上意味着实现 IReader 接口方法的 任何 类型将被归类为实现该接口的类型,因此是可以接受的。由于类型 *Reader 在您的示例中实现了 IReader 类型,因此它是此处 NewReader 函数可接受的 return 值。这意味着如果我引入一个实现此接口的新 type,例如

type dummy int

func (d dummy) GetCount() int {
    return d
}

func (d dummy) IncreaseCount() {
    fmt.Println("Increased count: %d", d)
}

然后我可以做类似的事情

func NewReader() IReader {
    var d dummy
    d = 5
    return d
}

它仍然有效。使用 reflect 包进行检查时,此 returned 值的基础类型将是 dummy.