我知道我可以写这样的代码,但我不知道它是如何工作的:
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
?
答案 0 :(得分:3)
这是一个嵌入式结构,来自http://golang.org/doc/effective_go.html#embedding:
通过直接嵌入结构,我们避免了这种记账。该 嵌入式类型的方法是免费的,这意味着 bufio.ReadWriter不仅有bufio.Reader和方法 bufio.Writer,它也满足所有三个接口:io.Reader, io.Writer和io.ReadWriter。
嵌入与子类化不同的重要方法。 当我们嵌入一个类型时,那种类型的方法成为了方法 外部类型,但是当它们被调用时,方法的接收者是 内在的类型,而不是外在的类型。在我们的例子中,当读 调用bufio.ReadWriter的方法,它具有完全相同的方法 作为上述转发方法的效果;接收器是 ReadWriter的reader字段,而不是ReadWriter本身。
嵌入也可以是一种简单的方便。这个例子显示了一个 嵌入字段和常规命名字段。
TL; DR:
这或多或少是“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)
}
答案 1 :(得分:2)
这称为嵌入。如果您还没有阅读Effective Go,那么您应该这样做。 http://golang.org/doc/effective_go.html#embedding
简而言之,嵌入式http.Transport
的方法可以通过MyTransport
struct访问。
答案 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
}
但是为了推广字段的方法并满足io接口,我们还需要提供转发方法,如下所示:
func (rw *ReadWriter) Read(p []byte) (n int, err error) {
return rw.reader.Read(p)
}
将其视为"将所有结构定义及其方法复制到此结构"
答案 3 :(得分:0)
为什么我不必在MyTransport中为传输提供名称
您已创建匿名字段,因此非限定类型名称将作为字段名称
有关详细信息,请参阅spec here:
使用类型但没有显式字段名称声明的字段是匿名字段,也称为嵌入字段或在结构中嵌入类型。必须将嵌入类型指定为类型名称T或指向非接口类型名称* T的指针,并且T本身可能不是指针类型。非限定类型名称用作字段名称