golang 結構體中的匿名接口
代碼示例
golang 中,可以給結構體增加匿名field,可參考 unknwon 大神的書。
但,golang同時也可以給結構體定義一個匿名interface field,用法:
標准庫 sort
中,有下面的寫法:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
type reverse struct {
Interface
}
func (r reverse) Less(i, j int) bool {
return r.Interface.Less(j, i)
}
func Reverse(data Interface) Interface {
return &reverse{data}
}
reverse結構體內嵌了一個Interface
的interface,並且,提供了單獨的Less
函數定義。
卻沒有提供 Len
, Swap
的定義。
首先,根據結構體內嵌其它匿名字段的定義,可以推知,理論上,調用reverse.Len
, reverse.Swap
,
肯定是會直接傳遞到 reverse.Interface.Len
和 reverse.Interface.Swap
,
即,和直接調用Interface的同名函數沒有任何區別。
但,reverse
提供了單獨的Less
函數,它的實現是顛倒了i,j
參數,仍然送入到Interface.Less
中去,
那么,得出的結果與直接使用Interface排序的結果,肯定是相反的。
為什么如此設計?
Meaning of a struct with embedded anonymous interface?
摘錄其中比較關鍵的解釋如下:
- In this way
reverse
implements thesort.Interface
and we can override a specific method without having to define all the others. - 結構體創建時,可以使用任何實現了
Interface
的obj來初始化,參考:
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"})
}