嵌入式自定义接口

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

Go embedded custom interfaces

问题

我正在尝试理解Go语言中的接口和嵌入。

我想要做的是创建自己的自定义writerreader,其中每个都实现了io.Writerio.Reader接口。

现在,我想要将这些实现基本接口的自定义结构嵌入到另一个实现了Read/Write/Close接口的自定义结构中。以下是我目前的代码,但是当我运行它时,会出现以下错误:

cannot use test (type MyReadWriteCloser) as type io.Writer in argument to fmt.Fprintf: MyReadWriteCloser does not implement io.Writer (missing Write method)

我以为当你在一个结构体中嵌入另一个结构体时,你也会获得嵌入结构体的方法。有人可以告诉我我漏掉了什么吗?

package main

import (
	"fmt"
	"io"
)

type MyWriter struct {
	w io.Writer
}

func (m MyWriter) Write(b []byte) (n int, err error) {
    // encrypt b and write to underlying writer
	m.w.Write(b)
	return
}

type MyReader struct {
	r io.Reader
}

func (m MyReader) Read(b []byte) (n int, err error) {
    // decrypt b
	m.r.Read(b)
	return
}

type MyReadWriteCloser struct {
	MyWriter
	MyReader
}

func (m MyReadWriteCloser) Close() error {
	return nil
}

func main() {
	fmt.Println("main start")

	r, w := io.Pipe()

	test := MyReadWriteCloser{
		MyWriter{w},
		MyReader{r},
	}
	fmt.Fprintf(test, "hello world\n")
}
英文:

I'm trying to understand Go's interfaces and embedding.

What I'm trying to do here is create my own custom writer and reader where each one implements either io.Writer or io.Reader

Now I want to take these custom structures that implement basic interfaces and embed them into another custom struct that implements Read/Write/Close. The below code is what I have so far but when I run it I get the following error

cannot use test (type MyReadWriteCloser) as type io.Writer in argument to fmt.Fprintf:
MyReadWriteCloser does not implement io.Writer (missing Write method)

I thought when you embed a structure within another structure you also get the methods of the embedded structures. Can someone tell me what I'm missing?

package main

import (
"fmt"
"io"
)

type MyWriter struct {
	w io.Writer
}

func (m MyWriter) Write(b []byte) (n int, err error) {
    // encrypt b and write to underlying writer
	m.w.Write(b)
	return
}

type MyReader struct {
	r io.Reader
}

func (m MyReader) Read(b []byte) (n int, err error) {
    // decrypt b
	m.r.Read(b)
	return
}

type MyReadWriteCloser struct {
	MyWriter
	MyReader
}

func (m MyReadWriteCloser) Close() error {
	return nil
}

func main() {
	fmt.Println("main start")

	r, w := io.Pipe()

	test := MyReadWriteCloser{
		MyWriter{w},
		MyReader{r},
	}
	fmt.Fprintf(test, "hello world\n")
} 

答案1

得分: 2

你没有嵌入接口,而是将它们作为结构体中的字段。

嵌入的写法如下:

type MyReader struct {
    io.Reader
}

如果你想手动委托给接口,你需要使用相同的方法名

func (m MyReader) Read(b []byte) (n int, err error) {
    return m.r.Read(b)
}
英文:

You're not embedding the interfaces, you're making them fields in your struct.

Embedding looks like:

type MyReader struct {
    io.Reader
}

If you want to manually delegate to the interface, you need to use the same method name

func (m MyReader) Read(b []byte) (n int, err error) {
    return m.r.Read(b)
}

答案2

得分: 0

你的语法有误,因此接口/类型实际上没有被嵌入。

type MyWriter struct {
    w io.Writer
}

应该改为

type MyWriter struct {
    io.Writer
}

根据我的理解,如果正确嵌入了类型,就没有必要定义像这样的方法:

func (m MyWriter) Write(b []byte) (n int, err error) {
    m.w.Write(b)
    return
}

因为方法体应该只是 m.Write(b),所以这样做没有意义。如果嵌入了一个类型,嵌入类型将能够直接调用嵌入类型的方法(这是最接近继承的东西,对于一个普通读者来说看起来是一样的)。我不记得在嵌入类型或嵌入类型与嵌入类型之间的方法或属性名称冲突时的解决规则,但一个好的经验法则是避免嵌入会导致命名冲突的类型,因为行为将不明显。

编辑:
以下是如何覆盖底层类型中的方法并从其中调用“基础”方法的示例:

func (m MyWriter) Write(b []byte) (n int, err error) {
     b = EncodeBFromMethodThatsInScopeHere(b)
     return m.Writer.Write(b)
}

基本上,如果你想显式地使用嵌入类型的方法,你可以将其作为类型的属性引用,就像它是一个属性名一样。

英文:

Your syntax is wrong so the interfaces/types are not actually being imbedded.

type MyWriter struct {
    w io.Writer
}

should be

type MyWriter struct {
    io.Writer
}

And based on my understanding a proper embed leaves you no reason to define a method like;

func (m MyWriter) Write(b []byte) (n int, err error) {
    m.w.Write(b)
    return
}

because the body would just be m.Write(b) so that just doesn't make sense. If you embed a type the embedding type will be able to call methods from the embedded type directly (it's the nearest thing to inheritance, it looks the same to a casual reader). I don't remember the resolution rules if there are conflicts between method or property names in embedded types or the embedding type an embedded type but a good rule of thumb would be to avoid embedding types that will cause naming conflicts because the behavior will not be obvious.

EDIT:
Example of how to override a method in the underlying type and invoke the 'base' (i quote cause some gophers might be offended by that word choice) method from inside it;

func (m MyWriter) Write(b []byte) (n int, err error) {
     b = EncodeBFromMethodThatsInScopeHere(b)
     return m.Writer.Write(b)
}

Basically, if you want to explicitly use the embedded types method you can refer to it as a property of the type using the embedded types type as if it were a property name.

huangapple
  • 本文由 发表于 2015年4月4日 04:34:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/29439311.html
匿名

发表评论

匿名网友

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

确定