Calculator with History

A calculator that uses closures to maintain operation history, variadic functions for multi-operand math, and defer to print a summary at the end.

package main

import "fmt"

func makeCalculator() (func(string, ...float64) float64, func() []string) {
	var history []string

	calc := func(op string, nums ...float64) float64 {
		if len(nums) == 0 {
			return 0
		}

		result := nums[0]
		for _, n := range nums[1:] {
			switch op {
			case "add":
				result += n
			case "sub":
				result -= n
			case "mul":
				result *= n
			case "div":
				if n != 0 {
					result /= n
				}
			}
		}

		entry := fmt.Sprintf("%s(%v) = %.2f", op, nums, result)
		history = append(history, entry)
		return result
	}

	getHistory := func() []string {
		return history
	}

	return calc, getHistory
}

func divide(a, b float64) (float64, error) {
	if b == 0 {
		return 0, fmt.Errorf("cannot divide %.2f by zero", a)
	}
	return a / b, nil
}

func main() {
	calc, getHistory := makeCalculator()

	defer func() {
		fmt.Println("\n--- Session Summary ---")
		for i, entry := range getHistory() {
			fmt.Printf("  %d. %s\n", i+1, entry)
		}
		fmt.Printf("  Total operations: %d\n", len(getHistory()))
	}()

	sum := calc("add", 10, 20, 30, 5)
	fmt.Printf("add(10, 20, 30, 5) = %.2f\n", sum)

	product := calc("mul", 3, 4, 5)
	fmt.Printf("mul(3, 4, 5) = %.2f\n", product)

	diff := calc("sub", 100, 25, 10)
	fmt.Printf("sub(100, 25, 10) = %.2f\n", diff)

	quotient := calc("div", 100, 4, 5)
	fmt.Printf("div(100, 4, 5) = %.2f\n", quotient)

	// Multiple return values with error handling
	result, err := divide(10, 3)
	if err != nil {
		fmt.Println("Error:", err)
	} else {
		fmt.Printf("divide(10, 3) = %.4f\n", result)
	}

	_, err = divide(5, 0)
	if err != nil {
		fmt.Println("Error:", err)
	}
}
▶ Open Go Playground

Copy the code above and paste to run

© 2026 ByteLearn.dev. Free courses for developers. · Privacy