Go Interfaces: Shape Calculator
Go's interfaces are a powerful mechanism for achieving polymorphism and decoupling. This challenge will test your understanding of how to define and implement interfaces in Go to create a flexible shape calculation system. You will need to define an interface that represents a generic shape and then implement this interface for different geometric shapes.
Problem Description
Your task is to create a system that can calculate the area and perimeter of various geometric shapes using Go interfaces. You will define an Shape interface that outlines the common behaviors expected of any shape (calculating area and perimeter). Then, you will implement this Shape interface for at least two different geometric shapes, such as a Circle and a Rectangle. Finally, you will write a function that accepts a slice of Shape interfaces and calculates the total area and perimeter of all shapes within that slice.
Key Requirements:
- Define a
ShapeInterface: This interface should have two methods:Area() float64: Returns the area of the shape.Perimeter() float64: Returns the perimeter of the shape.
- Implement
ShapeforCircle:- A
Circleshould be defined by itsRadius(afloat64). - Implement the
Area()method forCircleusing the formula: $\pi \times radius^2$. - Implement the
Perimeter()method forCircleusing the formula: $2 \times \pi \times radius$.
- A
- Implement
ShapeforRectangle:- A
Rectangleshould be defined by itsWidthandHeight(bothfloat64). - Implement the
Area()method forRectangleusing the formula: $width \times height$. - Implement the
Perimeter()method forRectangleusing the formula: $2 \times (width + height)$.
- A
- Create a
CalculateTotalMetricsFunction: This function should:- Accept a slice of
Shapeinterfaces ([]Shape). - Iterate through the slice, calling
Area()andPerimeter()on each shape. - Return the sum of all areas and the sum of all perimeters as two
float64values.
- Accept a slice of
Expected Behavior:
The system should correctly calculate the area and perimeter for each individual shape and aggregate them correctly when passed to the CalculateTotalMetrics function.
Edge Cases:
- Shapes with zero dimensions (e.g., a circle with radius 0, a rectangle with width/height 0) should result in 0 area and 0 perimeter.
- The input slice to
CalculateTotalMetricscould be empty. In this case, the function should return 0 for both total area and total perimeter.
Examples
Example 1:
Input:
shapes := []Shape{
Circle{Radius: 5.0},
Rectangle{Width: 4.0, Height: 6.0},
}
Output:
Total Area: 103.53981633974483
Total Perimeter: 57.67944963603789
Explanation:
- Circle Area: $\pi \times 5^2 = 78.53981633974483$
- Circle Perimeter: $2 \times \pi \times 5 = 31.41592653589793$
- Rectangle Area: $4 \times 6 = 24.0$
- Rectangle Perimeter: $2 \times (4 + 6) = 20.0$
- Total Area: $78.53981633974483 + 24.0 = 102.53981633974483$
- Total Perimeter: $31.41592653589793 + 20.0 = 51.41592653589793$
Example 2:
Input:
shapes := []Shape{
Circle{Radius: 0.0},
Rectangle{Width: 10.0, Height: 0.0},
}
Output:
Total Area: 0.0
Total Perimeter: 20.0
Explanation:
- Circle Area: $\pi \times 0^2 = 0.0$
- Circle Perimeter: $2 \times \pi \times 0 = 0.0$
- Rectangle Area: $10.0 \times 0.0 = 0.0$
- Rectangle Perimeter: $2 \times (10.0 + 0.0) = 20.0$
- Total Area: $0.0 + 0.0 = 0.0$
- Total Perimeter: $0.0 + 20.0 = 20.0$
Example 3: (Empty Slice)
Input:
shapes := []Shape{}
Output:
Total Area: 0.0
Total Perimeter: 0.0
Explanation: An empty slice should result in zero total area and perimeter.
Constraints
- All dimensions (
Radius,Width,Height) will be non-negativefloat64values. - The value of $\pi$ should be taken from the
mathpackage (math.Pi). - Performance is not a critical concern for this challenge; focus on correctness and idiomatic Go.
Notes
- Remember that Go interfaces are satisfied implicitly. You don't need to explicitly declare that a type implements an interface.
- Consider how you will represent $\pi$ in your calculations. The
mathpackage is your friend here. - Think about the return types of your
AreaandPerimetermethods. They should befloat64to handle potential decimal values. - You might want to create a main function to test your implementations with the example inputs.