package main import "fmt" func main() { foo1() } type Payer interface { Pay(int) error } // ----------------------------------------------------------------------------- type Wallet struct { Cash int } func (w *Wallet) Pay(amount int) error { if w.Cash < amount { return fmt.Errorf("Не хватает денег в кошельке") } w.Cash -= amount return nil } // ----------------------------------------------------------------------------- type Card struct { Balance int ValidUntil string Cardholder string CVV string Number string } func (c *Card) Pay(amount int) error { if c.Balance < amount { return fmt.Errorf("Не хватает денег на карте") } c.Balance -= amount return nil } // ----------------------------------------------------------------------------- type ApplePay struct { Money int AppleID string } func (a *ApplePay) Pay(amount int) error { if a.Money < amount { return fmt.Errorf("Не хватает денег на аккаунте") } a.Money -= amount return nil } // ----------------------------------------------------------------------------- // Здесь напрямую нельзя обриться к полю структуры, реализующей интерфейс. // Поэтому нужно делать преобразвание. func Buy(p Payer) { switch p.(type) { case *Wallet: fmt.Println("Oplata наличными?") case *Card: plasticCard, ok := p.(*Card) if !ok { fmt.Println("Не удалось преобразовать к типу *Card") } fmt.Println("Вставляйте карту,", plasticCard.Cardholder) default: fmt.Println("Что-то новое!") } err := p.Pay(10) if err != nil { fmt.Println(err) } else { fmt.Printf("Спасибо за покупку через %T\n\n", p) } } func foo1() { // myWallet := &Wallet{Cash: 100} // Buy(myWallet) var myMoney Payer myMoney = &Card{Balance: 100, Cardholder: "rvasily"} Buy(myMoney) myMoney = &ApplePay{Money: 9} Buy(myMoney) }