Go言語(golang)のinterface{}を型アサーション/型キャスト
アサーション(assertion)の意味は断定、断言なので、型を断定
するですかね。
interface型をアサートするには、i.(T)
を使います。
複数から判別したい場合は、switch文で i.(type)
を使います。
構造体type xxx struct
やインターフェースtype xxx interface
についても同様です。
インターフェース型にする
// 1 var i interface{} i = true // 2 var i interface{} = 100 // 3 i := interface{}("hello")
型アサーション
以下のようにすると、変数 s は文字列型になります。
func main() { i := interface{}("hello") s := i.(string) }
型が間違っていると、パニックする
func main() { i := interface{}("hello") s := i.(int) // panic! }
パニックしないように型が合っているかどうかを確認するには、
2つめの変数を受け取り、その真偽値で判定できます。
以下の型が間違っている変数 n
はint型でゼロ値になる
func main() { i := interface{}("hello") n, ok := i.(int) fmt.Println(n, ok) // 0 false s, ok := i.(string) fmt.Println(n, ok) // hello true }
switchで複数から判別する
i.(type)
はswitch文のみで使うことができます。
package main func main() { i := interface{}(100) switch i.(type) { case string: s := i.(string) println("i is string:", s) case bool: b := i.(bool) println("i is boolean:", b) case int: n := i.(int) println("i is integer:", n) // i is integer: 100 } }
細かく判別できる
package main func main() { var v int64 = 100 i := interface{}(v) switch i.(type) { case int32: println("int32") case int16: println("int16") case int64: println("int64") // int64 } }
構造体(struct)
type struct も同じように変換できる
package main type A struct{} func main() { i := interface{}(A{}) _, ok := i.(A) println("A:", ok) }
インターフェース(interface)
type interface で定義した要件を満たしているかどうかの判別にも i.(T)
が使えます。
package main type A struct { } type B struct { } func (b B) Hello(name string) { println("hello", name) } type Interface interface { Hello(name string) } func main() { var ok bool // A の構造体は Hello メソッドを持っていないので false a := interface{}(A{}) _, ok = a.(Interface) println("A:", ok) // A: false // B の構造体は Hello メソッドを持っているので true b := interface{}(B{}) _, ok = b.(Interface) println("B:", ok) // B: true }
この具体例が、Go言語のflagパッケージの929行目にあって type boolFlag interface
かどうかを判定してます。
https://golang.org/src/flag/flag.go#L929