Overview
If goroutine and channel are the two cornerstones of Go concurrency, then interfaces are the key to data types in Go programming. In actual programming of Go, almost all data structures revolve around interfaces, which are the core of all data structures in Go.
An interface in Go is a method set that specifies the behavior of an object: if it (any data type) can do these things, then it can be used here.
Definition and use of interfaces
for example
type I interface{
Get() int
Put(int)
}
This passage defines an interface, which contains two functions Get and Put
OK, one of my interfaces implements this interface:
type S struct {val int}
func (this *S) Get int {
return
}
func (this *S)Put(v int) {
= v
}
This structure S implements interface I
How to write interface in Go
Here are a few examples of interfaces:
func SomeFunction(w interface{Write(string)}){
("pizza")
}
In this example, it is very special to define the interface directly in the parameter...
func weirdFunc( i int ) interface{} {
if i == 0 {
return "zero"
}
return i;
}
Interface assignment
We can assign an object instance to an interface that implements an interface, or we can assign another interface to an interface.
(1) Assign value through object instance
Before assigning an object instance to an interface, you must ensure that the object implements all methods of the interface. Consider the following example:
type Integer int
func (a Integer) Less(b Integer) bool {
return a < b
}
func (a *Integer) Add(b Integer) {
*a += b
}
type LessAdder interface {
Less(b Integer) bool
Add(b Integer)
}
var a Integer = 1
var b1 LessAdder = &a //OK
var b2 LessAdder = a //not OK
The assignment of b2 will report a compilation error. Why? Do you still remember the provisions of the Go language specifications discussed in the Chapter <Type Method>?
The method set of any other named type T consists of all methods with receiver type T. The method set of the corresponding pointer type T is the set of all methods with receiver T or T (that is, it also contains the method set of T).
In other words, *Integer implements all methods of the interface LessAdder, while Integer only implements Less method, so it cannot assign values.
(2) Assign value through interface
var r = new()
var rw = r //not ok
var rw2 = new()
var r2 = rw2 //ok
Because r does not have a Write method, it cannot be assigned to rw.
Interface nesting
Let's take a look at another interface in the io package:
// ReadWriter is the interface that groups the basic Read and Write methods.
type ReadWriter interface {
Reader
Writer
}
This interface is nested with two interfaces, which is actually equivalent to the following writing method:
type ReadWriter interface {
Read(p []byte) (n int, err error)
Write(p []byte) (n int, err error)
}
Note that interfaces in Go cannot be recursively nested.
// illegal: Bad cannot embed itself
type Bad interface {
Bad
}
// illegal: Bad1 cannot embed itself using Bad2
type Bad1 interface {
Bad2
}
type Bad2 interface {
Bad1
}
empty interface
The empty interface is quite special, it does not contain any methods:
In Go, all other data types implement empty interfaces.
var v1 interface{} = 1
var v2 interface{} = "abc"
var v3 interface{} = struct{ X int }{1}
If the function intends to receive any data type, the reference can be declared as interface{}. The most typical example is the Print and Fprint series functions in the standard library fmt package:
func Fprint(w , a ...interface{}) (n int, err error)
func Fprintf(w , format string, a ...interface{})
func Fprintln(w , a ...interface{})
func Print(a ...interface{}) (n int, err error)
func Printf(format string, a ...interface{})
func Println(a ...interface{}) (n int, err error)
Note that []T cannot be assigned directly to []interface{}
t := []int{1, 2, 3, 4}
var s []interface{} = t
The following error will be output during compilation:
cannot use t (type []int) as type []interface {} in assignment
We must use the following method:
t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
s[i] = v
}