Go's `switch` is more general than C's. The expressions need not be constants or even integers, the cases are evaluated top to bottom until a match is found, and if the `switch` has no expression it switches on *true*. It's therefore possible — and idiomatic — to write an `if-else-if-else` chain as a `switch`. ```go func unhex(c byte) byte { switch { case '0' <= c && c <= '9': return c - '0' case 'a' <= c && c <= 'f': return c - 'a' + 10 case 'A' <= c && c <= 'F': return c - 'A' + 10 } return 0 } ``` There is no automatic fall through, but cases can be presented in comma-separated lists. ```go func shouldEscape(c byte) bool { switch c { case ' ', '?', '&', '=', '#', '+', '%': return true } return false } ``` Although they are not nearly as common in Go as some other C-like languages, `break` statements can be used to terminate a `switch` early. Sometimes, though, it's necessary to break out of a surrounding loop, not the switch, and in Go that can be accomplished by putting a label on the loop and "breaking" to that label. This example shows both uses. ```go Loop: for n := 0; n < len(src); n += size { switch { case src[n] < sizeOne: if validateOnly { break } size = 1 update(src[n]) case src[n] < sizeTwo: if n+1 >= len(src) { err = errShortInput break Loop } if validateOnly { break } size = 2 update(src[n] + src[n+1]< b func Compare(a, b []byte) int { for i := 0; i < len(a) && i < len(b); i++ { switch { case a[i] > b[i]: return 1 case a[i] < b[i]: return -1 } } switch { case len(a) > len(b): return 1 case len(a) < len(b): return -1 } return 0 } ``` # type switch A `switch` can also be used to discover the dynamic type of an interface variable. Such a `type switch` uses the syntax of a type assertion with the keyword `type` inside the parentheses. If the `switch` declares a variable in the expression, the variable will have the corresponding type in each clause. It's also idiomatic to reuse the name in such cases, in effect declaring a new variable with the same name but a different type in each case. ```go var t interface{} t = functionOfSomeType() switch t := t.(type) { default: fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has case bool: fmt.Printf("boolean %t\n", t) // t has type bool case int: fmt.Printf("integer %d\n", t) // t has type int case *bool: fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool case *int: fmt.Printf("pointer to integer %d\n", *t) // t has type *int } ```