技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

タイプアサーション、switch type【Go】

タイプアサーション

タイプアサーションとは、interfaceを型変換する機能です。
interfaceは中身に何も指定しないことで、「どのような型も受付ける」型を表現できます。
その受付けた型を、「<変数名>.(<型>)」の形でタイプアサーション(型変換)します。

func foo(i interface{}) {    // { }内に何も指定しないため、あらゆる型を受付けることができる
    ii := i.(int)    //int型に変換
    ii++    // interface → int に変換したため、エラーにならない
    fmt.Println(ii)
}

func main() {
    foo(2)    // 3
}


上記のままだと、main関数内で、例えばfoo("あ")とした時にpanicが発生します。
foo()が、int型以外への型変換に対応できていないからです。
switch type構文を使用することで、この問題を解決できます。

func foo(i interface{}) {
    switch v := i.(type) {    // iをinterface から型変換したものをvに格納する。その型の内容に応じてcaseに振り分ける
    case int:
        v++
        fmt.Println(v)
    case string:
        fmt.Println(v + "!")
    default:
        fmt.Printf("I couldn't deal with %T\n", v)
    }
}

func main() {
    foo(1)    // 2
    foo("Hi")    // Hi!
    foo(true)    // I couldn't deal with bool
    var fl float64 = 1.2
    foo(fl)    // I couldn't deal with float64
}


また、switch type 構文を用いた関数に返り値を持たせることもできます。
返り値はinterface{}としてあげます。

func foo(i interface{}) interface{} {    // 返り値はinterface{}
    switch v := i.(type) {
    case int:
        return v
    case string:
        return fmt.Sprintf("Yes, %v", v)    // fmt.Sprintfは、異なる型でもまとめてstringにする。文中に変数を組み込むことができる便利な機能
    default:
        return "undefined."
    }
}

func main() {
    fmt.Println(foo(3))    // 3
    fmt.Println(foo("A"))    // Yes, A
    fmt.Println(foo(true))    // undefined.
}