In golang, the function of inheritance and override is realized by combination. Perhaps most of us usually use the writing of anonymous struct in struct. Have you ever seen the writing of anonymous interface in struct?
Interface is an interface that is directly an anonymous segment in struct and is written in the standard library sort package as follows:
type Interface interface { Len() int Less(i, j int) bool Swap(i, j int) } type reverse struct { Interface }
Let's look at a complete example. The following code is extracted from the sort package:
package main import ( "fmt" ) type Interface interface { Len() int Less(i, j int) bool Swap(i, j int) } // Array Implements Interface Interface Interface type Array []int func (arr Array) Len() int { return len(arr) } func (arr Array) Less(i, j int) bool { return arr[i] < arr[j] } func (arr Array) Swap(i, j int) { arr[i], arr[j] = arr[j], arr[i] } // Anonymous interface type reverse struct { Interface } // Override func (r reverse) Less(i, j int) bool { return r.Interface.Less(j, i) } // Constructing reverse Interface func Reverse(data Interface) Interface { return &reverse{data} } func main() { arr := Array{1, 2, 3} rarr := Reverse(arr) fmt.Println(arr.Less(0,1)) fmt.Println(rarr.Less(0,1)) }
The purpose of this in the sort package is to rewrite the interfaces methods and make effective use of the original ones; a reverse Interface can be constructed from the Interface through Reverse. The go language takes advantage of the combination feature and rewrites only a few lines of code.
Comparing with the traditional rewriting method of combining anonymous structures, it may help us better understand the advantages of anonymous interfaces.
package main import ( "fmt" ) type Interface interface { Len() int Less(i, j int) bool Swap(i, j int) } type Array []int func (arr Array) Len() int { return len(arr) } func (arr Array) Less(i, j int) bool { return arr[i] < arr[j] } func (arr Array) Swap(i, j int) { arr[i], arr[j] = arr[j], arr[i] } // Anonymous struct type reverse struct { Array } // Rewrite func (r reverse) Less(i, j int) bool { return r.Array.Less(j, i) } // Constructing reverse Interface func Reverse(data Array) Interface { return &reverse{data} } func main() { arr := Array{1, 2, 3} rarr := Reverse(arr) fmt.Println(arr.Less(0, 1)) fmt.Println(rarr.Less(0, 1)) }
The above example uses the writing of anonymous structure, which implements the same rewriting function as the previous writing of anonymous interface, or even very similar. But if you compare it carefully, you will find the advantage of anonymous interface. The way of anonymous interface does not depend on the specific implementation, it can rewrite any type of interface that implements it. This is very useful when writing public libraries. If you often look at the source code of some libraries, anonymous interfaces should be written with great familiarity.
Another function of anonymous interfaces is to add some constraints to the structure, which must be constructed using the type of interface that implements it. The structure can contain some other fields, while the interface has only methods and no fields.
package main import ( "fmt" "reflect" "sort" ) type Array1 []int func (arr Array1) Len() int { return len(arr) } func (arr Array1) Less(i, j int) bool { return arr[i] < arr[j] } func (arr Array1) Swap(i, j int) { arr[i], arr[j] = arr[j], arr[i] } type Array2 []int func (arr Array2) Len() int { return len(arr) } func (arr Array2) Less(i, j int) bool { return arr[i] < arr[j] } func (arr Array2) Swap(i, j int) { arr[i], arr[j] = arr[j], arr[i] } type Sortable struct { sort.Interface // other field Type string } func NewSortable(i sort.Interface) Sortable { t := reflect.TypeOf(i).String() return Sortable{ Interface: i, Type: t, } } func DoSomething(s Sortable) { fmt.Println(s.Type) fmt.Println(s.Len()) fmt.Println(s.Less(0, 1)) } func main() { arr1 := Array1{1, 2, 3} arr2 := Array2{3, 2, 1, 0} DoSomething(NewSortable(arr1)) DoSomething(NewSortable(arr2)) }