Notice: Draft version

This is just draft version of how we organize code structure to follow open close principle in golang

Todo: class diagram

Shape interface, define must have GetArea() function

type Shape interface {
    GetArea() float64

Then Square struct which implement Shape interface

type Square struct {
    Width float64

func (s Square) GetArea() float64 {
    return s.Width*s.Width

Same as Square struct, the Circle struct

type Circle struct {
    Radius float64

func (c Circle) GetArea() float64 {
    return c.Radius * c.Radius * math.Pi

Then ShapeManager struct

type ShapeManager struct {
   shapes    []Shape

func (smgr *ShapeManager) AddShape(shape Shape) {
   smgr.shapes = append(smgr.shapes, shape)

func (smgr ShapeManager) GetTotalArea() float64 {
    total := 0.0 
    for _, shape := range smgr.shapes {
        total += shape.GetArea()
    return total

func NewShapeManager() ShapeManager {
    smgr := ShapeManager{}
    smgr.shapes = []Shape{}
    return smgr

Then, the main.go file

func main() {
    square := Square{10.0}
    circle := Circle{12.0}

    shapeManager := NewShapeManager()

    fmt.Println("Square Area ", square.GetArea())
    fmt.Println("Circle Area ", circle.GetArea())
    fmt.Println("Shape Manager Total Area ", shapeManager.GetTotalArea())

Whenever you add more type of shape, for eg: a rectangle:

// define Rectangle struct
type Rectangle struct {
    Length float64
    Width float64

func (r Rectangle) GetArea() float64 {
    return r.Width * r.Length

// add rectangle in main.go
rect := Rectangle{5.0, 6.0}
fmt.Println("Rectangle Area ", rect.GetArea())

fmt.Printf("shapeManager %+v\n", shapeManager)

fmt.Println("Shape Manager Total Area ", shapeManager.GetTotalArea())

It’s convenience when we wanna add more types of Shape and follow the O principle in SOLID

Gist file: