Go中的模糊转换语法

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

Ambiguous Conversion Syntax in Go

问题

我有以下类型定义:

type reader io.Reader

我希望这个 reader 类型实现 io.Reader 接口,所以我这样做:

func (r reader) Read(p []byte) (n int, err error) {
    return io.Reader(r).Read(p)
}

问题是:io.Reader(r) 可能有两种含义:

  • r 转换为其底层类型(io.Reader
  • 静态断言(由编译器检查) r 满足 io.Reader 接口(因为我们定义了一个 Read([]byte) (int, error) 方法,它满足接口)。创建一个新的 io.Reader 接口值并将 r 存储在其中。

我希望发生前者。如果发生后者,当我调用 io.Reader(r).Read(p) 时,它将调用 r 的底层 Read 方法(我们此刻正在其中),并且会无限循环。我希望发生的是提取 r 内部的底层 io.Reader,并使用它的 Read 方法。

当然,我可以通过实际测试来确定这两种情况中的哪一种发生,但我对 Go 编译器如何解决这些问题感到好奇。我在语言规范中找不到相关信息。

英文:

I have the following type definition:

type reader io.Reader

and I want this reader type to implement the io.Reader interface, so I do:

func (r reader) Read(p []byte) (n int, err error) {
    return io.Reader(r).Read(p)
}

The problem is this: io.Reader(r) could mean one of two things:

  • Convert r to its underlying type (io.Reader)
  • Assert statically (checked by compiler) that r satisfies the io.Reader interface (since we've defined a Read([]byte) (int, error) method, it does). Create a new io.Reader interface value and store r inside it.

I want the former to happen. If the latter happens, when I call io.Reader(r).Read(p), it will call r's underlying Read method (which we are inside at the moment), and it will infinite loop. What I would like to happen is to extract the underlying io.Reader inside r, and use its Read method.

Of course, I could just test to see in practice which of the two of these happens, but I'm curious in general about how these problems are resolved by the Go compiler. I couldn't find the relevant information in the language spec.

答案1

得分: 9

你不能将接口类型reader(定义为io.Reader)用作func (r reader) {}中的接收器类型。

你需要将reader类型定义为一个具体类型:

type reader struct {
    // stuff
}

回答你的问题,io.Reader(r)的意思是在编译时断言r满足io.Reader接口,并创建一个新的io.Reader接口值,并将r存储在其中(你的第二个选择)。

因此,如果你尝试上述操作,将会导致无限递归。

在Go语言中,底层的io.Reader的概念是没有意义的,因为你不能在接口上定义方法,只能在具体类型上定义方法。

当然,你可以在彼此之间嵌入类型,可能会像这样:

type reader struct {
    other io.Reader
}

然后你可以调用:

func (r reader) Read(p []byte) (n int, err error) {
    return r.other.Read(p)
}
英文:

You can't use an interface type reader which is defined as io.Reader as a receiver type in func (r reader) {}.

You need to define the reader type as a specific type

type reader struct {
    // stuff
}

To answer your question, the io.Reader(r) means assert at compile time that r satisfies the io.Reader interface and create a new io.Reader interface value and store r inside it. (your second choice).

So if you try the above you'll get an infinite recursion.

The idea of an underlying io.Reader makes no sense in Go since you can't define methods on interfaces, only on concrete types.

You can of course embed types within each other which might look like this

type reader struct {
    other io.Reader
}

Which you would then call

func (r reader) Read(p []byte) (n int, err error) {
    return r.other.Read(p)
}

答案2

得分: 0

我认为接收器方法只适用于结构体,此外,你正在尝试将一个接口实现为另一个接口。我不知道在Go语言中是否可能实现这一点。在其他语言中,比如Java,可以通过抽象类来解决这个问题,但是Go语言的核心中没有这个概念。

英文:

I think that the receiver method is only for Struct, Furthermore you are trying to implement one interface to another interface. I dont know if this is posible in go. In other languages like Java that implementation is solved with abstract class but GoLang do not have this topics in your core.

huangapple
  • 本文由 发表于 2014年4月16日 05:09:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/23094593.html
匿名

发表评论

匿名网友

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

确定