5

Here the famous "fizz buzz" program in Go using switch/case and if/else conditionals. The problem is that using switch/case is generating unexpected output while if/else (with same conditions) works fine. I know that switch/case in golang is different than other C-family languages, but what's wrong with this code fragment?

func main() {
const (
    FIZZ = 3
    BUZZ = 5
)

//section with switch/case gives unexpected output
for i := 1; i <= 30; i++ {
    switch {
    case i % FIZZ == 0:
        fmt.Printf("%d fizz\t", i%3)
        fallthrough
    case i % BUZZ == 0:
        fmt.Printf("%d buzz\t", i%5)
    }
    fmt.Printf("\t%d\n", i)
}

fmt.Printf("now towards the if/else\n")

//section with if/else works as expected
for i := 1; i <= 30; i++ {
    if i % FIZZ == 0 {
        fmt.Printf("%d fizz\t", i%3)
    }
    if i % BUZZ == 0 {
        fmt.Printf("%d buzz\t", i%5)
    }
    fmt.Printf("\t%d\n", i)
}

}

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189

3 Answers3

6

From the golang spec:

Fallthrough statements

A "fallthrough" statement transfers control to the first statement of the next case clause in a expression "switch" statement. It may be used only as the final non-empty statement in such a clause.

So the problem is: "case i % FIZZ == 0" has fallthrough at the end, so "case i % BUZZ == 0" branch is executed too, but the condition "i % BUZZ == 0" is not checked.

So to implement Fizz Buzz in golang using switch you need to remove fallthrough and add one more case branch to the top: play.golang.org. As you can see, "if-version" is more concise.

Kluyg
  • 5,119
  • 2
  • 25
  • 28
  • 2
    I was just about to answer the same thing :-) Example: http://play.golang.org/p/y9SAfTE5x5 (The second case in the switch should never be true, but the quote you gave gives the reason it's executed. – Intermernet Sep 11 '13 at 14:03
  • It'll take a little getting used to golang but it's fun. So to be crystal-clear, what exactly are the scenarios "fallthrough" is useful for? "...as the final non-empty statement in such a clause..." that's quite general. – Stack Exchange Sep 11 '13 at 14:25
  • Imagine that you need to print "fuzzbuzz" when i % 5 == 0 and only "buzz" when i % 3. Compare two versions: http://play.golang.org/p/kLQHV53rFh. One more syntetic example: http://play.golang.org/p/-H4uczxM6B. And from the real-life: http://golang.org/src/pkg/encoding/ascii85/ascii85.go#L43 – Kluyg Sep 11 '13 at 14:43
  • fallthrough is useful when you need to add additional behaviour to the behaviour in the next case block, for some specific condition – Kluyg Sep 11 '13 at 14:54
3

Your can use i%15 for fizzbuzz. This option gives a gain in performance. One number - one division and one system call (sys_write). And no worries about fallthrough. Play.

func main() {

    const (
        FIZZ = 3
        BUZZ = 5
        FIZZBUZZ = 15
   )

    for i := 1; i <= 30; i++ {
        switch {
        case i % FIZZBUZZ == 0:
            fmt.Printf("%d fizzbuzz\n", i)
        case i % FIZZ == 0:
            fmt.Printf("%d fizz\n", i)
        case i % BUZZ == 0:
            fmt.Printf("%d buzz\n", i)
        default:
             fmt.Printf("%d\n", i)
        }
   }
}
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Ivan Black
  • 4,827
  • 1
  • 35
  • 33
0
//Example - between 1 and 100.

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