Golang / GoLang Interfaces and Object Oriented Interview Questions
Walk through a complete Go OOP design: payment processing without inheritance.
A realistic scenario showing how Go's interfaces, composition, and implicit satisfaction replace classical OOP: a payment processing system that is extensible, testable, and loosely coupled — without a single inheritance relationship.
// ââ Interfaces ââââââââââââââââââââââââââââââââââââââââââââââââââ type PaymentProcessor interface { Process(amount float64, currency string) (txID string, err error) } type Refunder interface { Refund(txID string, amount float64) error } type FullPayment interface { PaymentProcessor Refunder } // ââ Concrete implementations ââââââââââââââââââââââââââââââââââââ type StripeProcessor struct{ apiKey string } func NewStripe(key string) *StripeProcessor { return &StripeProcessor{apiKey: key} } func (s *StripeProcessor) Process(amount float64, currency string) (string, error) { return "stripe_tx_" + uuid(), nil // call Stripe API } func (s *StripeProcessor) Refund(txID string, amount float64) error { return nil // call Stripe refund API } // Compile-time check var _ FullPayment = (*StripeProcessor)(nil) // ââ Service: depends on narrow interfaces âââââââââââââââââââââââ type OrderService struct { payments PaymentProcessor // only needs to charge } func (os *OrderService) PlaceOrder(amount float64) error { txID, err := os.payments.Process(amount, "USD") if err != nil { return fmt.Errorf("payment failed: %w", err) } log.Printf("order paid, tx=%s", txID) return nil } type RefundService struct { refunds Refunder // only needs to refund } func (rs *RefundService) Refund(txID string, amount float64) error { return rs.refunds.Refund(txID, amount) } // ââ Wiring (main) ââââââââââââââââââââââââââââââââââââââââââââââââ stripe := NewStripe(os.Getenv("STRIPE_KEY")) orderSvc := &OrderService{payments: stripe} // stripe as PaymentProcessor refundSvc := &RefundService{refunds: stripe} // stripe as Refunder // ââ Test mock ââââââââââââââââââââââââââââââââââââââââââââââââââââ type MockPayment struct{ txID string; err error } func (m *MockPayment) Process(float64, string) (string, error) { return m.txID, m.err } func TestPlaceOrder(t *testing.T) { svc := &OrderService{payments: &MockPayment{txID: "mock_tx"}} if err := svc.PlaceOrder(99.99); err != nil { t.Fatal(err) } }
More Related questions...