interface{}
型を使用するのに適したリソースが見つかりません。例えば
package main
import "fmt"
func weirdFunc(i int) interface{} {
if i == 0 {
return "zero"
}
return i
}
func main() {
var i = 5
var w = weirdFunc(5)
// this example works!
if tmp, ok := w.(int); ok {
i += tmp
}
fmt.Println("i =", i)
}
Goのinterface{}
を使用するための優れた入門書を知っていますか?
特定の質問:
あなたの例は動作します。これは簡易版です。
package main
import "fmt"
func weird(i int) interface{} {
if i < 0 {
return "negative"
}
return i
}
func main() {
var i = 42
if w, ok := weird(7).(int); ok {
i += w
}
if w, ok := weird(-100).(int); ok {
i += w
}
fmt.Println("i =", i)
}
Output:
i = 49
Type assertions を使用します。
タイプスイッチを行うこともできます。
switch v := myInterface.(type) {
case int:
// v is an int here, so e.g. v + 1 is possible.
fmt.Printf("Integer: %v", v)
case float64:
// v is a float64 here, so e.g. v + 1.0 is possible.
fmt.Printf("Float64: %v", v)
case string:
// v is a string here, so e.g. v + " Yeah!" is possible.
fmt.Printf("String: %v", v)
default:
// And here I'm feeling dumb. ;)
fmt.Printf("I don't know, ask stackoverflow.")
}
リフレクション(reflect.TypeOf()
)を使用して何かのタイプを取得でき、それが与える値(Type
)には印刷可能な文字列表現(String
メソッド)があります。
次に、スイッチとリフレクションの両方を使用して汎用マップをデコードする例を示します。したがって、タイプが一致しない場合は、リフレクションを使用してそれを把握し、次回にタイプを追加します。
var data map[string]interface {}
...
for k, v := range data {
fmt.Printf("pair:%s\t%s\n", k, v)
switch t := v.(type) {
case int:
fmt.Printf("Integer: %v\n", t)
case float64:
fmt.Printf("Float64: %v\n", t)
case string:
fmt.Printf("String: %v\n", t)
case bool:
fmt.Printf("Bool: %v\n", t)
case []interface {}:
for i,n := range t {
fmt.Printf("Item: %v= %v\n", i, n)
}
default:
var r = reflect.TypeOf(t)
fmt.Printf("Other:%v\n", r)
}
}
タイプスイッチは、反射のものでも使用できます。
var str = "hello!"
var obj = reflect.ValueOf(&str)
switch obj.Elem().Interface().(type) {
case string:
log.Println("obj contains a pointer to a string")
default:
log.Println("obj contains something else")
}
リフレクションKindsの引数をローカルタイプレシーバーに渡すことに基づいてブール値を返す方法を提供します(このようなものが見つからなかったため)。
まず、タイプreflect.Valueの匿名タイプを宣言します。
type AnonymousType reflect.Value
次に、潜在的な型を(インターフェイスとして)取り込むことができるローカル型AnonymousTypeのビルダーを追加します。
func ToAnonymousType(obj interface{}) AnonymousType {
return AnonymousType(reflect.ValueOf(obj))
}
次に、reflect.Kindに対してアサートするAnonymousType構造体の関数を追加します。
func (a AnonymousType) IsA(typeToAssert reflect.Kind) bool {
return typeToAssert == reflect.Value(a).Kind()
}
これにより、以下を呼び出すことができます。
var f float64 = 3.4
anon := ToAnonymousType(f)
if anon.IsA(reflect.String) {
fmt.Println("Its A String!")
} else if anon.IsA(reflect.Float32) {
fmt.Println("Its A Float32!")
} else if anon.IsA(reflect.Float64) {
fmt.Println("Its A Float64!")
} else {
fmt.Println("Failed")
}
ここでより長い、作業中のバージョンを見ることができます: https://play.golang.org/p/EIAp0z62B7