DEV Community

Naftuli Singer
Naftuli Singer

Posted on

Understanding Go Interfaces with a Practical Example

#go

One of the most powerful features in Go is interfaces. They allow different types to share behaviour without requiring inheritance or explicit declarations.

If you're coming from languages like Java or C#, Go interfaces can feel unusual at first because types don’t explicitly declare that they implement them.

Instead, if a type implements the required methods, it automatically satisfies the interface.

In the code below we'll walk through a small practical example showing how interfaces allow different implementations to behave differently while still sharing the same contract.

package main

import "fmt"

// Adjustable represents something whose balance can be increased or decreased.
type Adjustable interface {
    Add(amount float64)
    Subtract(amount float64)
    GetBalance() float64
}

//
// STANDARD WALLET
//

type StandardWallet struct {
    balance float64
}

// Constructor
func NewStandardWallet() *StandardWallet {
    return &StandardWallet{}
}

func (w *StandardWallet) Add(amount float64) {
    w.balance += amount
}

func (w *StandardWallet) Subtract(amount float64) {
    w.balance -= amount
}

func (w *StandardWallet) GetBalance() float64 {
    return w.balance
}

//
// WALLET WITH TRANSACTION FEE
//

type FeeWallet struct {
    balance float64
    fee     float64
}

// Constructor
func NewFeeWallet(fee float64) *FeeWallet {
    return &FeeWallet{fee: fee}
}

func (w *FeeWallet) Add(amount float64) {
    w.balance += amount
}

// Subtract applies an additional fee.
func (w *FeeWallet) Subtract(amount float64) {
    w.balance -= (amount + w.fee)
}

func (w *FeeWallet) GetBalance() float64 {
    return w.balance
}

//
// GENERIC LOGIC
//

// AdjustBalance works with any type that satisfies Adjustable.
func AdjustBalance(a Adjustable, add bool, amount float64) {
    if add {
        a.Add(amount)
    } else {
        a.Subtract(amount)
    }
}

func main() {

    standard := NewStandardWallet()
    feeWallet := NewFeeWallet(2)

    // Same logic applied to both implementations
    AdjustBalance(standard, true, 100)
    AdjustBalance(standard, false, 30)

    AdjustBalance(feeWallet, true, 100)
    AdjustBalance(feeWallet, false, 30)

    fmt.Println("Standard wallet balance:", standard.GetBalance())
    fmt.Println("Fee wallet balance:", feeWallet.GetBalance())
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)