Understanding Go Interface With Lego

The purpose of interface is to enable unrelated objects to communicate with each other. In order to communicate, both sides must follow a protocol. Like Lego, in order to put 2 pieces of brick together, you need to make sure they can "communicate" with each other. The bottom one's studs will fit the one on top's tubes. The designers (programmers) define the interfaces to let two bricks (objects) to communicate.

Interface in Go works slightly different from other languages. The way your type implements the interface is implicit. As long as your type implements the same methods that declared in the interface. For example, let's define a Washer interface and it has 2 methods: GetCleaner() and GetWaterVolume().

 1package main
 2
 3import (
 4	"fmt"
 5)
 6
 7type ClothWasher struct {
 8	target string
 9}
10
11type DishWasher struct {
12	target string
13}
14
15type Washer interface {
16	GetCleaner() string
17	GetWaterVolume() int
18}
19
20func StartWashing(w Washer) string {
21	cleaner := w.GetCleaner()
22	progress := fmt.Sprintf("start washing with %s", cleaner)
23
24	return progress
25}
26
27func StopWashing(w Washer) string {
28	vol := w.GetWaterVolume()
29	progress := fmt.Sprintf("rinsing with %d liters of water", vol)
30
31	return progress
32}
33
34func (d DishWasher) GetCleaner() string {
35	return "dishwashing liquid"
36}
37
38func (d DishWasher) GetWaterVolume() int {
39	return 2
40}
41
42func (c ClothWasher) GetCleaner() string {
43	return "detergent"
44}
45
46func (c ClothWasher) GetWaterVolume() int {
47	return 10
48}
49
50func main() {
51	c := ClothWasher{}
52	d := DishWasher{}
53
54	fmt.Println(StartWashing(c)) // start washing with detergent
55	fmt.Println(StopWashing(c)) // rinsing with 10 liters of water
56	fmt.Println(StartWashing(d)) // start washing with dishwashing liquid
57	fmt.Println(StopWashing(d)) // rinsing with 2 liters of water
58}

Now both StartWashing and StopWashing accept Washer interface as parameter. Which means as long as a type has both GetCleaner() and GetWater() methods, this type has already implicitly implemented Washer interface and able to use StartWashing and StopWashing methods directly.

In Go, You may also take the advandage of empty interface in your function paramter. An empty interface as paramter means you can pass in any type of data. But make sure you use it appropriately. For example fmt package's Println function takes an empty interface as parameter, which means it can print out any data type. By receiving empty interface in incorrect circumstances might also cause unexpected bug.