7.11 型アサーションと型switch
インタフェース型の変数が特定の具象型を持っているか、あるいはその具象型が別のインタフェースを実装しているかを調べるのに、Goには2つの方法がある。
7.11.1 型アサーション
型アサーションは実行時にチェックされ、カンマ ok イディオムでチェックしないとパニックを引き起こす危険性がある
code:go
type MyInt int
func main() {
var i any
var mine MyInt = 20
i = mine // mineの型はMyInt。iはanyなので代入できる
i2 := i.(int) // iに代入された型はMyIntなので、パニック!
fmt.Println(i2)
}
そのため、型アサーションに間違いがないと確信していても、カンマ ok イディオムを使用することを推奨
code:go
type MyInt int
func main() {
var i any
var mine MyInt = 20
i = mine
i2, ok := i.(int)
if !ok {
err := fmt.Errorf("iの型(値:%v)が想定外です", i)
fmt.Println(err.Error())
os.Exit(1) // プログラムを終了
}
fmt.Println(i2)
}
7.11.2 型switch
型switchはインタフェースが複数の型のいずれかである場合に使用する
code:go
func doThings(i any) {
switch j := i.(type) {
case nil: // iはnil。jの型はany
fmt.Printf(" case nil; i:%v(型:%T), j:%v(型:%T)\n", i, i, j, j)
case int: // jの型はint
fmt.Printf(" case int; i:%d(型:%T), j:%v(型:%T)\n", i, i, j, j)
case MyInt: // jの型はMyInt
fmt.Printf(" case MyInt; i:%d(型:%T), j:%v(型:%T)\n", i, i, j, j)
case io.Reader: // jの型はio.Reader
fmt.Printf(" case io.Reader; i:%v(型:%T), j:%v(型:%T)\n", i, i, j, j)
case string: // jは文字列
fmt.Printf(" case string; i:%s(型:%T), j:%v(型:%T)\n", i, i, j, j)
case bool, rune: // iはboonかruneなので、jの型はany
fmt.Printf(" case bool, rune; i:%v(型:%T), j:%v(型:%T)\n", i, i, j, j)
default: // iの型は不明。jの型はany
fmt.Printf(" default; i:%v(型:%T), j:%v(型:%T)\n", i, i, j, j)
}
}