github.com/packtpublishing/learning-functional-programming-in-go@v0.0.0-20230130084745-8b849f6d58c4/Chapter04/01_duck/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "errors" 6 "log" 7 ) 8 const DASHES = "----------------------" 9 10 type Pond struct { 11 BugSupply int 12 StrokesRequired int 13 } 14 15 type StrokeBehavior interface { 16 PaddleFoot(strokeSupply *int) 17 } 18 19 type EatBehavior interface { 20 EatBug(strokeSupply *int) 21 } 22 23 type SurvivalBehaviors interface { 24 StrokeBehavior 25 EatBehavior 26 } 27 28 29 type Duck struct{} 30 31 func (Duck) Stroke(s StrokeBehavior, strokeSupply *int, p Pond) (err error) { 32 for i := 0; i < p.StrokesRequired; i++ { 33 if *strokeSupply < p.StrokesRequired - i { 34 err = errors.New("Our duck died!") 35 } 36 s.PaddleFoot(strokeSupply) 37 } 38 return err 39 } 40 41 func (Duck) Eat(e EatBehavior, strokeSupply *int, p Pond) { 42 for i := 0; i < p.BugSupply; i++ { 43 e.EatBug(strokeSupply) 44 } 45 } 46 47 type Foot struct{} 48 func (Foot) PaddleFoot(strokeSupply *int) { 49 fmt.Println("- Foot, paddle!") 50 *strokeSupply-- 51 } 52 53 type Bill struct{} 54 func (Bill) EatBug(strokeSupply *int) { 55 *strokeSupply++ 56 fmt.Println("- Bill, eat a bug!") 57 } 58 59 func (d Duck) SwimAndEat(se SurvivalBehaviors, strokeSupply *int, ponds []Pond) { 60 for i := range ponds { 61 pond := &ponds[i] 62 err := d.Stroke(se, strokeSupply, *pond) 63 if err != nil { 64 log.Fatal(err) // the duck died! 65 } 66 d.Eat(se, strokeSupply, *pond) 67 } 68 } 69 70 type Capabilities struct { 71 StrokeBehavior 72 EatBehavior 73 strokes int 74 } 75 76 func displayDuckStats(c Capabilities, ponds []Pond) { 77 fmt.Printf("%s\n", DASHES) 78 fmt.Printf("Ponds Processed:") 79 for _, pond := range ponds { 80 fmt.Printf("\n\t%+v", pond) 81 } 82 fmt.Printf("\nStrokes remaining: %+v\n", c.strokes) 83 fmt.Printf("%s\n\n", DASHES) 84 } 85 86 87 func main() { 88 var duck Duck 89 capabilities := Capabilities{ 90 StrokeBehavior: Foot{}, 91 EatBehavior: Bill{}, 92 strokes: 5, 93 } 94 95 ponds := []Pond{ 96 {BugSupply: 1, StrokesRequired: 3}, 97 {BugSupply: 1, StrokesRequired: 2}, 98 } 99 duck.SwimAndEat(&capabilities, &capabilities.strokes, ponds) 100 displayDuckStats(capabilities, ponds) 101 102 ponds = []Pond{ 103 {BugSupply: 2, StrokesRequired: 3}, 104 } 105 duck.SwimAndEat(&capabilities, &capabilities.strokes, ponds) 106 displayDuckStats(capabilities, ponds) 107 } 108 109