Go Wiki: Switch

仕様: https://go.dokyumento.jp/ref/spec#Switch_statements

Goのswitch文は非常に便利です。一つには、各ケースの最後にbreakを記述する必要がないことです。

switch c {
case '&':
    esc = "&"
case '\'':
    esc = "'"
case '<':
    esc = "&lt;"
case '>':
    esc = "&gt;"
case '"':
    esc = "&quot;"
default:
    panic("unrecognized escape character")
}

src/pkg/html/escape.go

整数だけではない

switch文は任意の型の値で動作します。

switch syscall.OS {
case "windows":
    sd = &sysDir{
        Getenv("SystemRoot") + `\system32\drivers\etc`,
        []string{
            "hosts",
            "networks",
            "protocol",
            "services",
        },
    }
case "plan9":
    sd = &sysDir{
        "/lib/ndb",
        []string{
            "common",
            "local",
        },
    }
default:
    sd = &sysDir{
        "/etc",
        []string{
            "group",
            "hosts",
            "passwd",
        },
    }
}

式の欠落

実際には、何も切り替える必要はありません。値のないswitchは「switch true」を意味し、Effective Goのこの例のように、if-elseチェーンのよりクリーンなバージョンになります

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
}

Break

Goのswitch文は暗黙的にbreakしますが、breakは依然として便利です。

command := ReadCommand()
argv := strings.Fields(command)
switch argv[0] {
case "echo":
    fmt.Print(argv[1:]...)
case "cat":
    if len(argv) <= 1 {
        fmt.Println("Usage: cat <filename>")
        break
    }
    PrintFile(argv[1])
default:
    fmt.Println("Unknown command; try 'echo' or 'cat'")
}

フォールスルー

後続のケースにフォールスルーするには、fallthroughキーワードを使用します

v := 42
switch v {
case 100:
    fmt.Println(100)
    fallthrough
case 42:
    fmt.Println(42)
    fallthrough
case 1:
    fmt.Println(1)
    fallthrough
default:
    fmt.Println("default")
}
// Output:
// 42
// 1
// default

別の例

// Unpack 4 bytes into uint32 to repack into base 85 5-byte.
var v uint32
switch len(src) {
default:
    v |= uint32(src[3])
    fallthrough
case 3:
    v |= uint32(src[2]) << 8
    fallthrough
case 2:
    v |= uint32(src[1]) << 16
    fallthrough
case 1:
    v |= uint32(src[0]) << 24
}

src/pkg/encoding/ascii85/ascii85.go

「fallthrough」はケースの最後の記述である必要があります。次のような記述はできません。

switch {
case f():
    if g() {
        fallthrough // Does not work!
    }
    h()
default:
    error()
}

ただし、「ラベル付き」のfallthroughを使用することで、これを回避できます

switch {
case f():
    if g() {
        goto nextCase // Works now!
    }
    h()
    break
nextCase:
    fallthrough
default:
    error()
}

注: fallthroughはタイプswitchでは機能しません。

複数のケース

同じケースで複数の値を使用する場合は、カンマ区切りのリストを使用します。

func letterOp(code int) bool {
    switch chars[code].category {
    case "Lu", "Ll", "Lt", "Lm", "Lo":
        return true
    }
    return false
}

タイプswitch

タイプswitchを使用すると、インターフェース値(のみ)の型を切り替えることができます

func typeName(v interface{}) string {
    switch v.(type) {
    case int:
        return "int"
    case string:
        return "string"
    default:
        return "unknown"
    }
}

変数を宣言することもでき、それぞれのcaseの型になります

func do(v interface{}) string {
    switch u := v.(type) {
    case int:
        return strconv.Itoa(u*2) // u has type int
    case string:
        mid := len(u) / 2 // split - u has type string
        return u[mid:] + u[:mid] // join
    }
    return "unknown"
}

do(21) == "42"
do("bitrab") == "rabbit"
do(3.142) == "unknown"

Noopケース

何もしないケースがあると便利な場合があります。noopケースと後続のケースが同じアクションを持っているように見えることがあるため、これは混乱を招く可能性がありますが、そうではありません。

func pluralEnding(n int) string {
    ending := ""

    switch n {
    case 1:
    default:
        ending = "s"
    }

    return ending
}

fmt.Sprintf("foo%s\n", pluralEnding(1))  == "foo"
fmt.Sprintf("bar%s\n", pluralEnding(2))  == "bars"


このコンテンツはGo Wikiの一部です。