Start learning free

LESSON 252 OF 573 · FUNCTIONS & CLASSES

Rectangle Class in Go: A Struct with Methods

Practice O(1) Read the full explanation

A class bundles some values with the questions you can ask about them. Write a class Rectangle that remembers a rectangle's width and height, and can tell its area, its perimeter, and whether it is a square.

Implement the class Rectangle:

  • Rectangle(width, height) creates a rectangle with the given sizes.
  • area() returns the area of the rectangle: its width times its height.
  • perimeter() returns the perimeter: the length all the way around, twice the width plus twice the height.
  • isSquare() returns true if the width and the height are equal, and false otherwise.

Each line of the input is one rectangle: its width and its height. The test code first creates a Rectangle for every line, then asks each of them, in order, for its area, its perimeter and whether it is a square, and prints the three answers on one line, the boolean as True or False. So each object must keep its own sizes. The starter code spells these names the way your language does (in Go and Rust, Rectangle is a struct with methods).

 

Example 1:

Input:
    Rectangle(3, 4)
Output: 12 14 False
Explanation: The area is 3 · 4 = 12. Going around, the sides are 3 + 4 + 3 + 4 = 14.
The width and the height differ, so it isn't a square.

Example 2:

Input:
    Rectangle(5, 5)
Output: 25 20 True
Explanation: 5 · 5 = 25, and 4 sides of 5 make 20. Both sizes are 5: a square is a rectangle with equal sides.

Example 3:

Input:
    Rectangle(2, 10)
    Rectangle(10, 2)
Output:
20 24 False
20 24 False
Explanation: Two objects, each with its own sizes. Turning a rectangle on its side changes neither its area nor its perimeter.

 

Constraints:

  • 1 <= width, height <= 104
  • At most 10 rectangles per test.

Note:

Each method needs only the two sizes, so each one runs in O(1) time.

STEP 1 OF 5
    Ctrl + Enter to check

    GO · FUNCTIONS & CLASSES

    Rectangle Class in Go, explained

    Problem overview

    A rectangle has two numbers, a width and a height, and you can ask it questions about them. This lesson asks for a Rectangle that can answer three: its area, its perimeter, and whether it is a square.

    Go has no classes. The same idea is a struct, which bundles named fields, plus methods, which are functions attached to the struct. A constructor is an ordinary function, by convention named NewRectangle, that returns a filled-in struct.

    For NewRectangle(3, 4) the area is 12, the perimeter is 14 and isSquare() is false. For NewRectangle(5, 5) they are 25, 20 and true. Each rectangle keeps its own sizes, so two values never interfere with each other.

    Approach

    Nothing needs to be computed ahead of time. The struct stores only the two sizes, and every method works its answer out from them when it is called:

    • the area is width * height;
    • the perimeter walks around all four sides, width + height + width + height, which is 2 * (width + height);
    • the rectangle is a square exactly when the two sizes are equal.

    Each method is a single expression, so each runs in constant time.

    Step by step

    1. Declare the fields. Inside the struct, width and height, both int. Every Rectangle value carries its own copy of them.
    2. Write the constructor. NewRectangle returns a struct literal. In width: width, the name on the left is the field and the one on the right is the parameter.
    3. Write area. Multiply the two fields. The receiver, named this here, is the rectangle the method was called on.
    4. Write perimeter. Add the two sizes first, using parentheses, then double the sum.
    5. Write isSquare. A comparison already produces a bool, so return this.width == this.height directly. No if is needed.

    The solution in Go

    type Rectangle struct {
        width int
        height int
    }
    func NewRectangle(width int, height int) Rectangle {
        return Rectangle{width: width, height: height}
    }
    func (this Rectangle) area() int {
        return this.width * this.height
    }
    func (this Rectangle) perimeter() int {
        return 2 * (this.width + this.height)
    }
    func (this Rectangle) isSquare() bool {
        return this.width == this.height
    }
    

    Go details worth knowing:

    • The receiver. (this Rectangle) before the method name is what makes a function a method. The name is your choice. Many Go programmers write a short one such as r, but the lesson uses this, which reads like other languages.
    • Value receivers. These three methods only read the fields, so a value receiver is enough: the method gets a copy of the rectangle, and that is fine because nothing changes.
    • Lowercase names. width and height start with a lowercase letter, so code outside the package cannot see them. Methods and the constructor inside the package can.
    • The zero value. A Rectangle declared with var z Rectangle has both fields 0, so its area is 0 and isSquare() is true. The constructor is how you give a rectangle real sizes.

    Why store the sizes and not the answers

    The struct could also store the area and the perimeter in extra fields, filled in by the constructor. That would be a mistake for a beginner's class: three numbers that must always agree are three chances to get out of step. With only the width and the height stored, the other answers are always correct, because they are recomputed from the sizes each time they are asked for. Storing the smallest set of facts and deriving everything else is a good habit for any struct.

    A method or a plain function

    Go lets you write the same thing as a plain function, func area(r Rectangle) int, and call it as area(r). A method does the same job with a different call, r.area(). The method form keeps the struct and the questions you can ask it together, and it is the form the lesson's tests use.

    Using it

    Create values with the constructor and call the methods with a dot:

    for _, r := range []Rectangle{NewRectangle(3, 4), NewRectangle(5, 5), NewRectangle(2, 10), NewRectangle(10, 2)} {
        fmt.Println(r.width, r.height, "->", r.area(), r.perimeter(), r.isSquare())
    }
    

    This prints:

    3 4 -> 12 14 false
    5 5 -> 25 20 true
    2 10 -> 20 24 false
    10 2 -> 20 24 false
    

    The last two lines show that turning a rectangle on its side changes neither the area nor the perimeter. The lesson's tests print the boolean as True or False; that is the tests' output format, while Go itself spells it true and false.

    Structs are copied on assignment. After a := NewRectangle(3, 4) and b := a, setting b.width = 9 leaves a alone: a.area() is 12 and b.area() is 36.

    Edge cases and common mistakes

    • Forgetting the parentheses in the perimeter. 2 * this.width + this.height doubles only the width. For a 3 by 4 rectangle it gives 10 instead of 14.
    • Using = instead of ==. In isSquare, a single = is an assignment and does not compile as a condition.
    • Swapping field and parameter in the literal. Rectangle{width: height, height: width} compiles but builds a turned rectangle. Area and perimeter don't notice, but the stored sizes are wrong.
    • Treating a square as a special case. A square is just a rectangle whose sides are equal, so NewRectangle(5, 5) needs no separate type.
    Keep going with Go500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free