Menu
Coddy logo textTech

Using Interface Types

Part of the Logic & Flow section of Coddy's GO journey — lesson 15 of 68.

Now that you know how to define and implement interfaces, let's explore how to actually use interface types in your code. The real power of interfaces comes from being able to create variables and function parameters of an interface type.

You can declare a variable of an interface type and assign any value to it, as long as that value's type implements the interface. Here is a complete example — from declaring the interface, to implementing it, to using it:

type Shaper interface {
    Area() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14 * c.Radius * c.Radius
}

var shape Shaper
shape = Circle{Radius: 5.0}
fmt.Println(shape.Area()) // Works perfectly!

This becomes especially powerful when writing functions. Instead of writing separate functions for each concrete type, you can write one function that accepts the interface type:

func printArea(s Shaper) {
    fmt.Printf("Area: %.2f\n", s.Area())
}

This single function can now work with any type that implements the Shaper interface - whether it's a Circle, Rectangle, or any other shape you create in the future. The function doesn't need to know the specific type; it only cares that the type can calculate its area.

This approach makes your code more flexible and reusable, allowing you to write functions that work with multiple types through their shared behaviors.

quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

challenge icon

Challenge

Easy

In this challenge, you'll practice using interface types by creating a drawing application that can work with different geometric shapes. You'll create a function that accepts an interface type as a parameter, demonstrating how interfaces make your code flexible and reusable.

You will receive three inputs:

  • A string representing the shape type (either "circle" or "rectangle")
  • A string representing the first dimension (radius for circle, width for rectangle)
  • A string representing the second dimension (not used for circle, height for rectangle)

Your task is to:

  1. Define a Shape interface with one method signature: Area() that returns a float64
  2. Define a Circle struct with a Radius field (float64)
  3. Define a Rectangle struct with Width and Height fields (both float64)
  4. Implement the Area() method for both structs:
    • Circle area: 3.14159 × radius × radius
    • Rectangle area: width × height
  5. Create a function called printShapeInfo that takes a Shape interface as a parameter and prints the area in the format: "Area: [area]"
  6. Based on the input shape type, create the appropriate shape instance and call printShapeInfo with it

The area should be displayed with up to 7 decimal places, but trailing zeros should be removed (e.g., 15.70796 instead of 15.70796000). This challenge demonstrates how a single function can work with multiple types through their shared interface, making your code more flexible and maintainable.

Cheat sheet

You can declare variables of an interface type and assign any value that implements the interface:

var shape Shaper
shape = Circle{Radius: 5.0}
fmt.Println(shape.Area()) // Works perfectly!

Functions can accept interface types as parameters, making them work with any type that implements the interface:

func printArea(s Shaper) {
    fmt.Printf("Area: %.2f\n", s.Area())
}

This approach makes code more flexible and reusable by allowing functions to work with multiple types through their shared behaviors.

Try it yourself

package main

import (
	"fmt"
	"strconv"
)

// TODO: Define Shape interface with an Area() float64 method

// TODO: Define Circle struct with a Radius field (float64)

// TODO: Define Rectangle struct with Width and Height fields (float64)

// TODO: Implement Area() method for Circle (use 3.14159 for pi)

// TODO: Implement Area() method for Rectangle

// TODO: Define printShapeInfo function that accepts a Shape and prints its area

func main() {
	// Read input
	var shapeType string
	var dimension1 string
	var dimension2 string
	fmt.Scanln(&shapeType)
	fmt.Scanln(&dimension1)
	fmt.Scanln(&dimension2)

	// Convert string inputs to float64
	dim1, _ := strconv.ParseFloat(dimension1, 64)
	dim2, _ := strconv.ParseFloat(dimension2, 64)

	// TODO: Declare a Shape variable
	// TODO: If shapeType is "circle", assign a Circle using dim1 as Radius
	// TODO: If shapeType is "rectangle", assign a Rectangle using dim1 as Width and dim2 as Height
	// TODO: Call printShapeInfo with the created shape
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Logic & Flow