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