Tom Dalling - FizzBuzz In Too Much Detail - My Take - In Go

Click to see the full article. This is my take, in Go.

Goal

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

Easy

package main

import "fmt"

func main() {
  for i := 1; i <= 15; i++ {
    if (i % 3 == 0 && i % 5 == 0) {
      fmt.Println("FizzBuzz")
    } else if (i % 3 == 0) {
      fmt.Println("Fizz")
    } else if (i % 5 == 0) {
      fmt.Println("Buzz")
    } else {
      fmt.Println(i);
    }
  }
}

Less duplication

func main() {
  for i := 1; i <= 15; i++ {
    res := ""
    if (i % 3 == 0) {
      res += "Fizz"
    }
    if (i % 5 == 0) {
      res += "Buzz"
    }
    if (res == "") {
      res = fmt.Sprint(i);
    }
    fmt.Println(res)
  }
}

Avoid duplicating 3, 5, Fizz, Buzz, Println.

Parameterized with numbers and strings

func run(max int, triggers map[int]string) []string {
  all := []string{}
  for i := 1; i <= max; i++ {
    res := ""
    for number, word := range triggers {
      if (i % number == 0) {
        res += word
      }
    }
    if (res == "") {
      res = fmt.Sprint(i);
    }
    all = append(all, res)
  }
  return all
}

func main() {
  all := run(15, map[int]string{
    3: "Fizz",
    5: "Buzz",
  })
  for _, word := range all {
    fmt.Println(word)
  }
}

Parameterized with functions

type Trigger func(res *string, i int)

func run(max int, triggers []Trigger) []string {
  all := []string{}
  for i := 1; i <= max; i++ {
    res := ""
    for _, trigger := range triggers {
      trigger(&res, i)
    }
    all = append(all, res)
  }
  return all
}

func main() {
  all := run(15, []Trigger{
    func(res *string, i int) {
      if (i % 3 == 0) {
        *res += "Fizz"
      }
    },
    func(res *string, i int) {
      if (i % 5 == 0) {
        *res += "Buzz"
      }
    },
    func(res *string, i int) {
      if (*res == "") {
        *res = fmt.Sprint(i)
      }
    },
  })
  for _, word := range all {
    fmt.Println(word)
  }
}

Function that returns a function

type Trigger func(res *string, i int)

func run(max int, triggers []Trigger) []string {
  all := []string{}
  for i := 1; i <= max; i++ {
    res := ""
    for _, trigger := range triggers {
      trigger(&res, i)
    }
    all = append(all, res)
  }
  return all
}

func create(number int, word string) Trigger {
  return func(res *string, i int) {
    if (i % number == 0) {
      *res += word
    }
  }
}

func main() {
  all := run(15, []Trigger{
    create(3, "Fizz"),
    create(5, "Buzz"),
    func(res *string, i int) {
      if (*res == "") {
        *res = fmt.Sprint(i)
      }
    },
  })
  for _, word := range all {
    fmt.Println(word)
  }
}

Avoid duplicating the Trigger creation.

Channel

type Trigger func(res *string, i int)

func run(max int, all chan string, triggers []Trigger) {
  for i := 1; i <= max; i++ {
    res := ""
    for _, trigger := range triggers {
      trigger(&res, i)
    }
    all <- res
  }
  close(all)
}

func create(number int, word string) Trigger {
  return func(res *string, i int) {
    if (i % number == 0) {
      *res += word
    }
  }
}

func main() {
  all := make(chan string)
  go run(15, all, []Trigger{
    create(3, "Fizz"),
    create(5, "Buzz"),
    func(res *string, i int) {
      if (*res == "") {
        *res = fmt.Sprint(i)
      }
    },
  })
  for word := range all {
    fmt.Println(word)
  }
}