Though it's not immediately obvious, having these two structs define the Shape interface methods would be useful if a function's parameter is of the Shape interface.
1234567
funcPrintShapeArea(shapeShape){fmt.Println("Shape Area = ",shape.getArea())}funcPrintShapeDimensions(shapeShape){fmt.Println("Shape Dimensions",shape.getDimensions())}
So, instead of having a print function for each struct, there can be one print function that accepts the interface that each struct implements. This is for code cogency and to reduce redundant copy/paste code.
1 2 3 4 5 6 7 8 91011121314
rect:=Rectangle{2,4}circle:=Circle{3}PrintShapeDimensions(rect)// "Shape Dimensions [2 4]"PrintShapeDimensions(circle)// "Shape Dimensions [3]"PrintShapeArea(rect)// "Shape Area = 8"PrintShapeArea(circle)// "Shape Area = 25"
Let's go through a more practical example. Let's say we have a black-box function that takes the io.Reader interface (from io package) as a parameter
123
funchandleReader(rio.Reader){...}
Structs that implement io.Reader must implement the Read(p []byte) (n int, err error) method, such as *os.File and *bytes.Buffer Since these structs have the Read method and the handleReader function only cares that the input struct implements the Read method, handleReader can handle both *os.File and *bytes.Buffer inputs without compilation error. Of course, there are many more structs that implement the io.Reader interface, and handleReader can handle inputs of each struct without compilation error.
Empty Interface
An empty interface contains zero methods. Since every type implements at least zero methods, the empty interface can be used as an any type, if the developer uncertain about the types of a function, map valueType, etc. For example, any map, slice, struct implement at least zero methods; thus, they implement the empty interface.
Examples:
Empty Interface as a ValueType
1234567
sampleMap:=make(map[string]interface{})/*The next two pushes to the map are completely validsince the ValueType is an empty interface*/sampleMap["hello"]="there"sampleMap["brooklynn"]=99//sampleMap == map[brooklynn:99 hello:there]
In the above example, since strings and integers implement at least zero methods, they implement the empty interface, which allow each type to be added into sampleMap
Similar to the reasoning above, since strings, floats, and integers have at least zero methods, they implement the empty interface, allowing each to be an input to the printVariable function.