2016-08-25 17 views
0

ここではGolang newbieはここにあります。インターフェイス変数の型がエイリアスである場合、インターフェイス変数の基になる型をテストする方法

この質問の短いバージョンです:エイリアス化されたタイプである可能性のあるインターフェイス値がある場合、それが基本タイプであるかどうかをチェックする正しい方法は何ですか?

タイプアサーションとタイプスイッチが動作しないことがわかりました。

たとえば、次のプログラムでは、基になるタイプのという名前のタイプが自動的に生成されます。私はインターフェイス変数vを持っています。これはどんなタイプでも構いません。 vOriginの場合、そのFieldの値を使用したいと思います。

package main 

import (
    "fmt" 
) 

type Origin struct { 
    Field int 
} 

type Alias1 Origin 
type Alias2 Origin 
type Alias3 Origin 

// A bunch of other aliases 

func f(v interface{}) { 
    if _, ok := v.(Origin); ok { 
     fmt.Println("type assertion works") 
    } 

    switch v := v.(type) { 
    case Origin: 
     fmt.Println("type switch works") 
    case Alias1: 
     fmt.Printf("No... Alias1 Value: %v\n", v.Field) 
    case Alias2: 
     fmt.Printf("No... Alias2 Value: %v\n", v.Field) 
    default: 
     fmt.Printf("No... Alias3 Value: %T\n", v.(Origin).Field) 
    } 
} 

func main() { 
    f(Alias1{Field: 10}) 
    f(Alias2{Field: 10}) 
    f(Alias3{Field: 10}) 
} 

https://play.golang.org/p/3WjpX6NcfFに示すように、出力:

No... Alias1 Value: 10 
No... Alias2 Value: 10 
panic: interface conversion: interface is main.Alias3, not main.Origin 

正しい方法でしょうか? (私はOriginのエイリアス化されたタイプはすべてfにリストアップすることはできません。これらのエイリアス化されたタイプは自動的に生成されて散らばります。前もって感謝します!

=====編集1 =====

reflectパッケージを使用しようとしましたが、それでも解決策を持っていない:私ができる最短のhttps://play.golang.org/p/3LtG9ZOkQd

package main 

import (
    "fmt" 
    "reflect" 
) 

type Origin struct { 
    Field int 
} 

type Alias1 Origin 

// A bunch of other aliases 

func g(v interface{}) { 
    vt := reflect.TypeOf(v) 
    ot := reflect.TypeOf(Origin{}) 
    if vt.ConvertibleTo(ot) { 
     fmt.Printf("%T is convertible to Origin", v) 

     // panic: interface is main.Alias3, not main.Origin 
     // fmt.Printf("Value: %v\n", v.(Origin).Field) 

     // error: vt is not a type 
     // fmt.Printf("Value: %v\n", v.(vt).Field) 

     // error: cannot convert v (type interface {}) to type Origin: need type assertion 
     // fmt.Printf("Value: %v\n", Origin(v).Field) 

    } 
} 

func main() { 
    g(Alias1{Field: 10}) 
} 
+0

ちょうど考えられました - フィールドごとにフィールドを比較できますか?元のタイプとエイリアスタイプの両方のフィールドセットが同じに見えるhttps://play.golang.org/p/TY5eMrN4m9 – shibormot

+0

@shibormotうわー、それでも私はまだ "v"(インターフェース値) 'Origin'型として扱います。コンパイラは、 'v'の型が' Origin'と同じフィールドを持っていても、 'v'を' Origin'にキャストすることを許可しません。 – antiAgainst

+0

reflect.ValueOfとreflect.Convertはお友達https://play.golang.org/p/dspem2VnA7 – Darigaaz

答えて

1

(あなたのコード内の代わりに第三FMTの)

fmt.Printf("Value: %v\n", reflect.ValueOf(v).Convert(ot).Interface().(Origin).Field) 

:取得はこれです

反射を使用してvを原点タイプに変換します。しかし、型アサーションを使用するが、それは反映されます。値。それをOrigin型にキャストするには、それをインタフェース{}に変換してからOrigin型にアサートする必要があります。

+0

クール!これは私が探していたものです!実際には、私がすでに試したことからいくつかスクロールダウンします。とにかくありがとう! – antiAgainst

関連する問題