An interface type is a method set. If a type contains methods of the interface, it implements the interface.
A type can implement multiple interfaces. For instance all type implement the empty interface.
An interface may use a interface type name in place of a method specification. This is called embedding interface.
type ReadWriter interface {
Read(b Buffer) bool
Write(b Buffer) bool
}
type File interface {
ReadWriter // same as adding the methods of ReadWriter
Close()
}
The empty interface
A type of empty interface can be used to declare a generic data type.
E.g. Implementing a linked list in Golang.
A linked list is a linear data structure where each element is a separate object. Linked list elements or nodes are not stored at contiguous location; the elements are linked using pointers.
We could declare the linked list node struct as follows
type Node struct {
Next *Node
Data interface{}
}
//creates a New Node
func NewNode(d interface{}) *Node {
nn := Node{Data: d, Next: nil}
return &nn
}
//Append : Adds a node to linked list
func (n *Node) Append(d interface{}) {
nn := NewNode(d)
if n == nil {
n = nn
} else {
m := n
for m.Next != nil {
m = m.Next
}
m.Next = nn
}
}
This allows us to use the same struct to hold data of different types.
Here I use int as the data type for Node.Data
n := NewNode(0) // int Data
n.Append(3)
n.Append(9)
for m := n; m != nil; m = m.Next {
fmt.Println(m.Data)
}
I could also use string as the data type using the same struct that I defined above.
n1 := NewNode("a") //string Data
n1.Append("b")
n1.Append("c")
Here is the full example:
https://play.golang.org/p/fo_sSndTsmc
I also have examples of using the empty interface when Unmarshalling JSON in my other post: Custom Unmarshal JSON in Go
Useful interfaces in Go stdlib
Error Interface
The error type is an interface that has a method Error.
type error interface {
Error() string
}
The most commonly used implementation of the error interface is the errorString type in the errors package.
// errorString is a trivial implementation of error.type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
Handler Interface
The Handler Interface in the net/http package requires one method ServerHTTP
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
Within that same package you will find HandlerFunc implements the Handler interface.
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
The HandlerFunc makes it possible for us to pass in any function to make it a Handler. All we would have to do is wrap it in HandlerFunc.
http.Handle("/", http.HandlerFunc(indexHandlerHelloWorld))null
We can have also have our own struct that has fields and methods and implements the Handler Interface by defining the ServeHTTP method as a member of the struct.
Stringer Interface
The fmt package has a stringer interface. It can be implemented by a type that declares the String method.
type Stringer interface {
String() string
}
If a type implements the stringer interface, a call to fmt.Println or fmt.Printf of the variable of type will use that method.
E.g. If you want to print a struct in a formatted fashion with key names and values, the struct needs to implement the Stringer interface
type Family struct {
Name string
Age int
}
func (f *Family) String() string {
return fmt.Sprintf("Name: %s\t Age: %d", f.Name, f.Age)
}
func main() {
family := []Family{
{"Alice", 23},
{"David", 6},
{"Erik", 2},
{"Mary", 32},
}
for _, i := range family {
fmt.Println(&i)
}
}
https://play.golang.org/p/F7rNPyClwG4
The fmt package has other interfaces like Scanner, Formatter and State.
References
https://golang.org/ref/spec#Interface_types
One thought on “Interfaces in Go”