我有一个问题,无法理解为什么当返回类型是接口时可以使用地址运算符
func NewReader() IReader {
return &Reader{}
}
但是(当然(当返回类型是结构时不是
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
。
- 所以类型
IReader
隐藏了它是指针的事实 - 函数签名
func MyFuncReader(r IReader)
没有告诉我,一个指针或一个值被传递给了函数
样品
- 带接口的完整样本https://play.golang.org/p/1Db1Jybp0rP
- 无接口的完整样本https://play.golang.org/p/nPtu09yhe0C
如果函数的返回类型是接口类型,则可以返回实现该接口的任何值。规格:退货声明:
返回值可以显式地列在";返回";陈述每个表达式都必须是单值的,并且可以赋值给函数结果类型的相应元素。
在您的第一个示例中,Reader
具有带有指针接收器的方法,因此只有指向Reader
的指针(即*Reader
(实现IReader
接口。因此您必须返回&Reader{}
。
如果函数的返回类型为具体类型,则必须返回该具体类型的值,而不能返回指向该类型的指针值。
当返回类型为Reader
时
func NewReader() Reader { return &Reader{} // cannot use &Reader literal (type *Reader) as type Reader in return argument }
您不能使用指向Reader
类型的指针来代替Reader
类型。原因是他们不属于同一类型。
当您使用像IReader
这样的接口作为中的返回类型时
func NewReader() IReader { return &Reader{} }
这基本上意味着实现IReader
接口方法的任何类型都将被归类为实现该接口的类型,因此是可以接受的。由于类型*Reader
实现了示例中的IReader
类型,因此它是NewReader函数的可接受返回值。这意味着如果我引入一个新的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
包进行检查时,此返回值的基本类型将是dummy
。