タイプアサーション、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. }