英文:
Can I pass an *io.ReadCloser to a parameter with the type of *io.Reader
问题
我正在尝试编写一个带有类型为*io.Reader
的参数的函数。
func ReadSomething(r *io.Reader) {
// 使用读取器进行一些操作
}
但是当我尝试将一个更接近它的读取器的指针传递给它时:
func GetWebPage() {
resp, _ := http.Get(<url>)
ReadSomething(&(resp.Body))
}
我得到以下错误:cannot use &(resp.Body) (value of type *io.ReadCloser) as *io.Reader value
。
这对我来说毫无意义,一个解引用的读取器指针类型应该实现了Reader
的方法,那么为什么我不能将它作为参数传递给一个期望io.Reader
指针的函数呢?
英文:
I am trying to write a function with a parameter of type *io.Reader
func ReadSomething(r *io.Reader) {
<do something with a reader>
}
but then when I try to pass in a pointer to a reader closer to it
func GetWebPage() {
resp, _ := http.Get(<url>)
ReadSomething(&(resp.Body))
}
I get the following error: cannot use &(resp.Body) (value of type *io.ReadCloser) as *io.Reader value
.
This makes no sense to me, a dereferenced pointer to a read closer type should implement the methods of Reader
, so why am I not able then to pass it in as an argument to a function that expects a pointer to an io.Reader
?
答案1
得分: 3
io.ReadCloser
是一个接口类型,它是 io.Reader
接口类型的超集。所以,每当需要一个 io.Reader
时,你可以传递一个 io.ReadCloser
的值。
*io.Reader
并不是一个接口类型,它是一个指针(指向接口的指针),所以你不能传递 *io.ReadCloser
。
请注意,这些函数签名设计得很糟糕。你很少需要一个指向接口的指针(当你确实需要时,你会知道,可以参考这个示例)。只需使用接口类型,接口可以包装指针(如果需要的话)。
英文:
io.ReadCloser
is an interface type that is a superset of io.Reader
interface type. So whenever an io.Reader
is required, you may pass a value of io.ReadCloser
.
*io.Reader
is not an interface type though, it's a pointer (a pointer to interface), so you can't pass *io.ReadCloser
.
Please note that these function signatures are a terrible design. You rarely need a pointer to interface (you'll know when you do, see this for an example). Just use interface types, interfaces may wrap pointers if needed.
答案2
得分: 2
在Go语言中,有一个普遍的误解,即接口比它们实际上更具有神奇和粘合性。作为起点,不同类型之间的所有转换都必须是显式的,而接口是不同的类型。
接口只是对这个规则的一个狭窄例外:
在Go语言规范中的可赋值性规则(也适用于参数传递)中有这样的定义:
> 如果一个值x可以赋值给类型T("x is assignable to T"),那么[...]
>
> - T是一个接口类型,并且x实现了T。
换句话说,简单明了地说:
> 如果x实现了T,那么x可以赋值给T。
这实际上就是整个例外的全部内容,并且它并不试图广泛地将接口、实现和相关结构融合在一起。一旦你通过指针间接引用接口值,你就已经超出了枚举的范围。
英文:
It's a common misconception in Go that interfaces are more magical and gluey than they really are. As a starting point, all conversions between distinct types must be explicit, and interfaces are distinct types.
Interfaces only carve out a narrow exception to this rule:
Assignability Rules in the Go Specification (which extends to parameter passing).
> A value x is assignable to a variable of type T ("x is assignable to T") if [...]
>
> - T is an interface type and x implements T.
Or in other words, simple and plain:
> x is assignable to T if x implements T.
That's really the whole entire exception, and it makes no expansive effort to generally mesh interfaces, implementations, and structures thereof. As soon as you indirect your interface value through a pointer, you have stepped out of the enumerated territory.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论