Go language does not have the concept of a class directly. It, however, has a concept of an interface
as well as a struct
. I’ll illustrate how this can be used to build most of the inheritance constructs that a language like Java or C++ offers.
Inheritance
I’ll use the cliché example of a Rectangle
class and a Square
class that inherits from it.
package main import "errors" // Rectangle encapsulates a immutable rectangle type Rectangle struct { width int32 height int32 } // NewRectangle is the constructor of Rectangle func NewRectangle(width int32, height int32) (*Rectangle, error) { if width <= 0 { return nil, errors.New("width must be > 0") } if height <= 0 { return nil, errors.New("height must be > 0") } return &Rectangle{width, height}, nil } // Width returns the width // Guaranteed to be a positive number func (r Rectangle) Width() int32 { return r.width } // Height returns the height // Guaranteed to be a positive number func (r Rectangle) Height() int32 { return r.height } func (r Rectangle) Area() int64 { return int64(r.width) * int64(r.height) }
And the cliché Square
class that inherits from it
package main // Square struct embeds Rectangle struct // It gets all methods like Width() and Height() of the parent class // for free type Square struct { Rectangle } // NewSquare is the constructor for the Square1 class func NewSquare(side int32) (*Square, error) { rect, err := NewRectangle(side, side) if err != nil { return nil, err } return &Square{*rect}, nil }
Note: This all works fine, if the parent Rectangle class is immutable, however, if it is mutable, then it is better to use composition. However, that’s not a language-specific issue, so, worth discussing in a separate blog post about inheritance vs composition.
Implementation
Go supports interfaces as well. But unlike Java or C++, no explicit declaration is required.
For example, consider a Shape
interface
package main type Shape interface { // Area returns the area of the shape Area() int64 }
Now, if one adds the following code to the Rectangle struct then both Rectangle and Square will be implementing the shape interface.
// Area returns the area of the Rectangle func (r Rectangle) Area() int64 { return int64(r.width) * int64(r.height) }
The complete example can be seen at https://go.dev/play/p/exbTybm0GGK