Go Lang
• 2 min read
Interface
An interface type in Go is kind of like a definition. It defines and describes the exact methods that some other type must have.
type Stringer interface {
String() string
}
We say that something satisfies this interface (or implements this interface) if it has a method with the exact signature String() string.
type Book struct {
Title string
Author string
}
func (b Book) String() string {
return fmt.Sprintf("Book: %s - %s", b.Title, b.Author)
}
Wherever you see declaration in Go (such as a variable, function parameter or struct field) which has an interface type, you can use an object of any type so long as it satisfies the interface.
func WriteLog(s fmt.Stringer) {
log.Print(s.String())
}
Because this WriteLog() function uses the fmt.Stringer interface type in its parameter declaration, we can pass in any object that satisfies the fmt.Stringer interface.
package main
import (
"fmt"
"strconv"
"log"
)
// Declare a Book type which satisfies the fmt.Stringer interface.
type Book struct {
Title string
Author string
}
func (b Book) String() string {
return fmt.Sprintf("Book: %s - %s", b.Title, b.Author)
}
// Declare a Count type which satisfies the fmt.Stringer interface.
type Count int
func (c Count) String() string {
return strconv.Itoa(int(c))
}
// Declare a WriteLog() function which takes any object that satisfies
// the fmt.Stringer interface as a parameter.
func WriteLog(s fmt.Stringer) {
log.Print(s.String())
}
func main() {
// Initialize a Count object and pass it to WriteLog().
book := Book{"Alice in Wonderland", "Lewis Carrol"}
WriteLog(book)
// Initialize a Count object and pass it to WriteLog().
count := Count(3)
WriteLog(count)
}
output:
2009/11/10 23:00:00 Book: Alice in Wonderland - Lewis Carrol
2009/11/10 23:00:00 3
Advantage
- To help reduce duplication or boilerplate code.
- To make it easier to use mocks instead of real objects in unit tests.
- As an architectural tool, to help enforce decoupling between parts of your codebase.
the empty interface type interface{} is kind of like a wildcard. Wherever you see it in a declaration (such as a variable, function parameter or struct field) you can use an object of any type.
package main
import "fmt"
func main() {
person := make(map[string]interface{}, 0)
person["name"] = "Alice"
person["age"] = 21
person["height"] = 167.64
fmt.Printf("%+v", person)
}
Error Handling
The error type is an interface type. An error variable represents any value that can describe itself as a string. Here is the interface’s declaration:
type error interface {
Error() string
}