好的,接受的答案帮助我理解了,但我决定发布一个我认为更适合我的思维方式的解释。
"Effective Go" 有嵌入其他接口的接口示例:
// ReadWriter is the interface that combines the Reader and Writer interfaces.
type ReadWriter interface {
Reader
Writer
}
以及嵌入了其他结构的结构:
// ReadWriter stores pointers to a Reader and a Writer.
// It implements io.ReadWriter.
type ReadWriter struct {
*Reader // *bufio.Reader
*Writer // *bufio.Writer
}
但是没有提到嵌入接口的结构。在sort 包中看到这个我很困惑:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
...
type reverse struct {
Interface
}
但是这个想法很简单。这几乎是一样的:
type reverse struct {
IntSlice // IntSlice struct attaches the methods of Interface to []int, sorting in increasing order
}
IntSlice 提升为reverse 的方法。
还有这个:
type reverse struct {
Interface
}
表示sort.reverse 可以嵌入任何实现接口sort.Interface 的结构,并且该接口具有的任何方法都将被提升为reverse。
sort.Interface 有方法 Less(i, j int) bool 现在可以被覆盖:
// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
return r.Interface.Less(j, i)
}
我的理解混乱
type reverse struct {
Interface
}
是不是我认为结构总是具有固定的结构,即固定类型的固定数量的字段。
但以下证明我错了:
package main
import "fmt"
// some interface
type Stringer interface {
String() string
}
// a struct that implements Stringer interface
type Struct1 struct {
field1 string
}
func (s Struct1) String() string {
return s.field1
}
// another struct that implements Stringer interface, but has a different set of fields
type Struct2 struct {
field1 []string
dummy bool
}
func (s Struct2) String() string {
return fmt.Sprintf("%v, %v", s.field1, s.dummy)
}
// container that can embedd any struct which implements Stringer interface
type StringerContainer struct {
Stringer
}
func main() {
// the following prints: This is Struct1
fmt.Println(StringerContainer{Struct1{"This is Struct1"}})
// the following prints: [This is Struct1], true
fmt.Println(StringerContainer{Struct2{[]string{"This", "is", "Struct1"}, true}})
// the following does not compile:
// cannot use "This is a type that does not implement Stringer" (type string)
// as type Stringer in field value:
// string does not implement Stringer (missing String method)
fmt.Println(StringerContainer{"This is a type that does not implement Stringer"})
}