August 29, 2015

# FizzBuzz in Golang

FizzBuzz goes like so:

Write a program that prints the numbers 1 to 100.

For multiples of three, print "Fizz".

For multiples of five, print "Buzz".

For multiples of both three and five, print "FizzBuzz".

In a hurry? Fast-forward to the Wrapup for working code.

## Qualifying the problem

Let's start by breaking things down into pseudo-code using the FizzBuzz problem statement:

Write a program that prints the numbers 1 to 100.

``````for i = 1; i <= 100; i++
print i

1
2
3
4
...
``````

For multiples of three, print "Fizz".

``````for i = 1; i <= 100; i++
if i % 3 == 0
print "Fizz"
else
print i

1
2
Fizz
4
5
Fizz
7
...
``````

For multiples of five, print "Buzz".

``````for i = 1; i <= 100; i++
if i % 3 == 0
print "Fizz"
else if i % 5 == 0
print "Buzz"
else
print i

1
2
Fizz
4
Buzz
Fizz
7
...
``````

For multiples of both three and five, print "FizzBuzz".

``````for i = 1; i <= 100; i++
if i % 15 == 0
print "FizzBuzz"
else if i % 3 == 0
print "Fizz"
else if i % 5 == 0
print "Buzz"
else
print i

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

## Solving it

Now that we have some pseudo-code, let's translate it to into Go:

``````package main

import "fmt"

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

When we run our program, we can see that the output is correct:

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

Congrats - unicorns have been saved and the world is well.

Run this code

### An Optimization

The above solution worked, but it's not perfect:

• Our first conditional, `if i%15 == 0`, is ran every time, even though it's only true every 15 times.
• We've duplicated the strings `Fizz` and `Buzz` between the calls to `fmt.Println`.

With a little fancy business, we can remedy both these issues:

``````package main

import "fmt"

func main() {
for i := 1; i <= 100; i++ {
result := ""
if i%3 == 0 { result += "Fizz" }
if i%5 == 0 { result += "Buzz" }
if result != "" {
fmt.Println(result)
continue
}
fmt.Println(i)
}
}
``````

Now we don't need to calculate `i%15 == 0` at all, and we never repeat ourselves. Win.

Run this code

## Writing tests

Because we are all good programmers who verify our programs, let's move our fizzbuzz functionality to its own testable function. For bonus points, we're going to add an `amount` param to the function that determines how many numbers to output:

``````func FizzBuzz(amount int) string {
results := ""
for i := 1; i <= amount; i++ {
result := ""
if i%3 == 0 { result += "Fizz" }
if i%5 == 0 { result += "Buzz" }
if result != "" {
results += result + "\n"
continue
}
results += fmt.Sprintf("%d\n", i)
}
return results
}
``````

Now we could call the function from main, or from a test like so:

``````func TestFizzBuzz(t *testing.T) {
got := FizzBuzz(15)
want :=
`1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
`
if got != want {
t.Errorf("FizzBuzz(15) \n got: \n%v \n want: \n%v", got, want)
}
}
``````

Run this code

## Using a Goroutine

As a final improvement, we're going to run our `FizzBuzz` function in a goroutine, streaming it's results through a channel that the main function will read from to progressivly output the results:

``````package main

import "fmt"

func main() {
for out := range FizzBuzz(100) {
fmt.Println(out)
}
}

func FizzBuzz(amount int) <-chan string {

out := make(chan string, amount)

go func() {
for i := 1; i <= amount; i++ {
result := ""
if i%3 == 0 { result += "Fizz" }
if i%5 == 0 { result += "Buzz" }
if result == "" { result = fmt.Sprintf("%v", i) }
out <- result
}
close(out)
}()

return out
}
``````

Run this code

## Wrapup

Here are 4 runnable Go programs for solving FizzBuzz: