|  | // run | 
|  |  | 
|  | // Copyright 2009 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // Test switch statements. | 
|  |  | 
|  | package main | 
|  |  | 
|  | import "os" | 
|  |  | 
|  | func assert(cond bool, msg string) { | 
|  | if !cond { | 
|  | print("assertion fail: ", msg, "\n") | 
|  | panic(1) | 
|  | } | 
|  | } | 
|  |  | 
|  | func main() { | 
|  | i5 := 5 | 
|  | i7 := 7 | 
|  | hello := "hello" | 
|  |  | 
|  | switch true { | 
|  | case i5 < 5: | 
|  | assert(false, "<") | 
|  | case i5 == 5: | 
|  | assert(true, "!") | 
|  | case i5 > 5: | 
|  | assert(false, ">") | 
|  | } | 
|  |  | 
|  | switch { | 
|  | case i5 < 5: | 
|  | assert(false, "<") | 
|  | case i5 == 5: | 
|  | assert(true, "!") | 
|  | case i5 > 5: | 
|  | assert(false, ">") | 
|  | } | 
|  |  | 
|  | switch x := 5; true { | 
|  | case i5 < x: | 
|  | assert(false, "<") | 
|  | case i5 == x: | 
|  | assert(true, "!") | 
|  | case i5 > x: | 
|  | assert(false, ">") | 
|  | } | 
|  |  | 
|  | switch x := 5; true { | 
|  | case i5 < x: | 
|  | assert(false, "<") | 
|  | case i5 == x: | 
|  | assert(true, "!") | 
|  | case i5 > x: | 
|  | assert(false, ">") | 
|  | } | 
|  |  | 
|  | switch i5 { | 
|  | case 0: | 
|  | assert(false, "0") | 
|  | case 1: | 
|  | assert(false, "1") | 
|  | case 2: | 
|  | assert(false, "2") | 
|  | case 3: | 
|  | assert(false, "3") | 
|  | case 4: | 
|  | assert(false, "4") | 
|  | case 5: | 
|  | assert(true, "5") | 
|  | case 6: | 
|  | assert(false, "6") | 
|  | case 7: | 
|  | assert(false, "7") | 
|  | case 8: | 
|  | assert(false, "8") | 
|  | case 9: | 
|  | assert(false, "9") | 
|  | default: | 
|  | assert(false, "default") | 
|  | } | 
|  |  | 
|  | switch i5 { | 
|  | case 0, 1, 2, 3, 4: | 
|  | assert(false, "4") | 
|  | case 5: | 
|  | assert(true, "5") | 
|  | case 6, 7, 8, 9: | 
|  | assert(false, "9") | 
|  | default: | 
|  | assert(false, "default") | 
|  | } | 
|  |  | 
|  | switch i5 { | 
|  | case 0: | 
|  | case 1: | 
|  | case 2: | 
|  | case 3: | 
|  | case 4: | 
|  | assert(false, "4") | 
|  | case 5: | 
|  | assert(true, "5") | 
|  | case 6: | 
|  | case 7: | 
|  | case 8: | 
|  | case 9: | 
|  | default: | 
|  | assert(i5 == 5, "good") | 
|  | } | 
|  |  | 
|  | switch i5 { | 
|  | case 0: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 1: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 2: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 3: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 4: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | assert(false, "4") | 
|  | case 5: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 6: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 7: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 8: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 9: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | default: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | assert(i5 == 5, "good") | 
|  | } | 
|  |  | 
|  | fired := false | 
|  | switch i5 { | 
|  | case 0: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough // tests scoping of cases | 
|  | case 1: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 2: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 3: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 4: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | assert(false, "4") | 
|  | case 5: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 6: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 7: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 8: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | case 9: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fallthrough | 
|  | default: | 
|  | dummy := 0 | 
|  | _ = dummy | 
|  | fired = !fired | 
|  | assert(i5 == 5, "good") | 
|  | } | 
|  | assert(fired, "fired") | 
|  |  | 
|  | count := 0 | 
|  | switch i5 { | 
|  | case 0: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | case 1: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | case 2: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | case 3: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | case 4: | 
|  | count = count + 1 | 
|  | assert(false, "4") | 
|  | case 5: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | case 6: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | case 7: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | case 8: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | case 9: | 
|  | count = count + 1 | 
|  | fallthrough | 
|  | default: | 
|  | assert(i5 == count, "good") | 
|  | } | 
|  | assert(fired, "fired") | 
|  |  | 
|  | switch hello { | 
|  | case "wowie": | 
|  | assert(false, "wowie") | 
|  | case "hello": | 
|  | assert(true, "hello") | 
|  | case "jumpn": | 
|  | assert(false, "jumpn") | 
|  | default: | 
|  | assert(false, "default") | 
|  | } | 
|  |  | 
|  | fired = false | 
|  | switch i := i5 + 2; i { | 
|  | case i7: | 
|  | fired = true | 
|  | default: | 
|  | assert(false, "fail") | 
|  | } | 
|  | assert(fired, "var") | 
|  |  | 
|  | // switch on nil-only comparison types | 
|  | switch f := func() {}; f { | 
|  | case nil: | 
|  | assert(false, "f should not be nil") | 
|  | default: | 
|  | } | 
|  |  | 
|  | switch m := make(map[int]int); m { | 
|  | case nil: | 
|  | assert(false, "m should not be nil") | 
|  | default: | 
|  | } | 
|  |  | 
|  | switch a := make([]int, 1); a { | 
|  | case nil: | 
|  | assert(false, "m should not be nil") | 
|  | default: | 
|  | } | 
|  |  | 
|  | // switch on interface. | 
|  | switch i := interface{}("hello"); i { | 
|  | case 42: | 
|  | assert(false, `i should be "hello"`) | 
|  | case "hello": | 
|  | assert(true, "hello") | 
|  | default: | 
|  | assert(false, `i should be "hello"`) | 
|  | } | 
|  |  | 
|  | // switch on implicit bool converted to interface | 
|  | // was broken: see issue 3980 | 
|  | switch i := interface{}(true); { | 
|  | case i: | 
|  | assert(true, "true") | 
|  | case false: | 
|  | assert(false, "i should be true") | 
|  | default: | 
|  | assert(false, "i should be true") | 
|  | } | 
|  |  | 
|  | // switch on interface with constant cases differing by type. | 
|  | // was rejected by compiler: see issue 4781 | 
|  | type T int | 
|  | type B bool | 
|  | type F float64 | 
|  | type S string | 
|  | switch i := interface{}(float64(1.0)); i { | 
|  | case nil: | 
|  | assert(false, "i should be float64(1.0)") | 
|  | case (*int)(nil): | 
|  | assert(false, "i should be float64(1.0)") | 
|  | case 1: | 
|  | assert(false, "i should be float64(1.0)") | 
|  | case T(1): | 
|  | assert(false, "i should be float64(1.0)") | 
|  | case F(1.0): | 
|  | assert(false, "i should be float64(1.0)") | 
|  | case 1.0: | 
|  | assert(true, "true") | 
|  | case "hello": | 
|  | assert(false, "i should be float64(1.0)") | 
|  | case S("hello"): | 
|  | assert(false, "i should be float64(1.0)") | 
|  | case true, B(false): | 
|  | assert(false, "i should be float64(1.0)") | 
|  | case false, B(true): | 
|  | assert(false, "i should be float64(1.0)") | 
|  | } | 
|  |  | 
|  | // switch on array. | 
|  | switch ar := [3]int{1, 2, 3}; ar { | 
|  | case [3]int{1, 2, 3}: | 
|  | assert(true, "[1 2 3]") | 
|  | case [3]int{4, 5, 6}: | 
|  | assert(false, "ar should be [1 2 3]") | 
|  | default: | 
|  | assert(false, "ar should be [1 2 3]") | 
|  | } | 
|  |  | 
|  | // switch on channel | 
|  | switch c1, c2 := make(chan int), make(chan int); c1 { | 
|  | case nil: | 
|  | assert(false, "c1 did not match itself") | 
|  | case c2: | 
|  | assert(false, "c1 did not match itself") | 
|  | case c1: | 
|  | assert(true, "chan") | 
|  | default: | 
|  | assert(false, "c1 did not match itself") | 
|  | } | 
|  |  | 
|  | // empty switch | 
|  | switch { | 
|  | } | 
|  |  | 
|  | // empty switch with default case. | 
|  | fired = false | 
|  | switch { | 
|  | default: | 
|  | fired = true | 
|  | } | 
|  | assert(fired, "fail") | 
|  |  | 
|  | // Default and fallthrough. | 
|  | count = 0 | 
|  | switch { | 
|  | default: | 
|  | count++ | 
|  | fallthrough | 
|  | case false: | 
|  | count++ | 
|  | } | 
|  | assert(count == 2, "fail") | 
|  |  | 
|  | // fallthrough to default, which is not at end. | 
|  | count = 0 | 
|  | switch i5 { | 
|  | case 5: | 
|  | count++ | 
|  | fallthrough | 
|  | default: | 
|  | count++ | 
|  | case 6: | 
|  | count++ | 
|  | } | 
|  | assert(count == 2, "fail") | 
|  |  | 
|  | i := 0 | 
|  | switch x := 5; { | 
|  | case i < x: | 
|  | os.Exit(0) | 
|  | case i == x: | 
|  | case i > x: | 
|  | os.Exit(1) | 
|  | } | 
|  |  | 
|  | // Unified IR converts the tag and all case values to empty | 
|  | // interface, when any of the case values aren't assignable to the | 
|  | // tag value's type. Make sure that `case nil:` compares against the | 
|  | // tag type's nil value (i.e., `(*int)(nil)`), not nil interface | 
|  | // (i.e., `any(nil)`). | 
|  | switch (*int)(nil) { | 
|  | case nil: | 
|  | // ok | 
|  | case any(nil): | 
|  | assert(false, "case any(nil) matched") | 
|  | default: | 
|  | assert(false, "default matched") | 
|  | } | 
|  | } |