仅在Go语言中将结构体类型指定为结构体成员是什么意思?

6
我知道我可以写出下面这样的代码,但我不知道它是如何工作的:
type MyTransport struct {
  http.Transport
}

func (myT *MyTransport) RoundTrip(r *http.Request) (*http.Response, error) {
  return myT.Transport.RoundTrip(r)
}

http.Transport只是一个结构体,它没有名称。那么myT.Transport是如何工作的呢?为什么在MyTransport中不需要给传输命名,例如像这样声明ht http.Transport?

4个回答

4
这是一个嵌入式结构体,来自于http://golang.org/doc/effective_go.html#embedding
通过直接嵌入结构体,我们避免了这种繁琐的工作。嵌入类型的方法会随之而来,这意味着bufio.ReadWriter不仅具有bufio.Reader和bufio.Writer的方法,还满足所有三个接口:io.Reader,io.Writer和io.ReadWriter。
嵌入方式与子类化有一个重要区别。当我们嵌入一个类型时,该类型的方法成为外部类型的方法,但当调用它们时,方法的接收器是内部类型,而不是外部类型。在我们的示例中,当调用bufio.ReadWriter的Read方法时,它与上面编写的转发方法完全相同;接收器是ReadWriter的reader字段,而不是ReadWriter本身。
嵌入也可以是一种简单的便利。此示例显示了一个嵌入字段和一个常规命名字段并存的情况。
简而言之,这是go语言实现“oop”继承的方式,或多或少。
type MyTransport struct {
    http.Transport
}

//without this function, calling myT.RoundTrip would actually call myT.Transport.RoundTrip
func (myT *MyTransport) RoundTrip(r *http.Request) (*http.Response, error) {
    return myT.Transport.RoundTrip(r)
}

2

2
那种语言的特性被称为嵌入: http://golang.org/doc/effective_go.html#embedding 如果文档内容过多,可以阅读相关部分以了解为什么要编写。
type MyTransport struct {
  http.Transport
}

代替
type MyTransport struct {
  transport http.Transport
}

这是什么:

// ReadWriter stores pointers to a Reader and a Writer.
// It implements io.ReadWriter.
type ReadWriter struct {
    *Reader  // *bufio.Reader
    *Writer  // *bufio.Writer
}

嵌入的元素是指向结构体的指针,当然在使用之前必须初始化为指向有效的结构体。ReadWriter结构体可以写成:
type ReadWriter struct {
    reader *Reader
    writer *Writer
}

为了推广这些领域的方法并满足输入/输出接口,我们还需要提供转发方法,例如:

func (rw *ReadWriter) Read(p []byte) (n int, err error) {
    return rw.reader.Read(p)
}

把它看作“将所有结构定义及其方法复制到此结构中”。

0
为什么在MyTransport中我不需要给传输命名?
您创建了一个匿名字段,因此未限定的类型名称充当字段名称。
有关更多详细信息,请参见此处的规范
声明了一个类型但没有显式字段名称的字段是匿名字段,也称为嵌入字段或将类型嵌入结构中。嵌入类型必须指定为类型名称T或非接口类型名称*T的指针,并且T本身不能是指针类型。未限定的类型名称充当字段名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接