Go言語のreflect.TypeOf()とreflect.Type(リフレクションを通じて型情報を取得)

Go言語のreflect.TypeOf()とreflect.Type(リフレクションを通じて型情報を取得)

 
 
Go では、reflect.TypeOf 関数を呼び出すことで、非インターフェイス型の値から Reflect.Type 値を作成できます。 Reflect.Type 値は、この非インターフェイス値のタイプを示します。この値を通じて、この非インターフェイス型に関する多くの情報を取得できます。もちろん、インターフェース値をreflect.TypeOf関数呼び出しに渡すこともできますが、この呼び出しは、このインターフェース値の動的タイプを表すreflect.Type値を返します。

 

実際、reflect.TypeOf 関数の唯一のパラメータは、interface{} 型であり、reflect.TypeOf 関数は常に、この一意のインターフェース パラメータ値の動的タイプを表す Reflect.Type 値を返します。

では、特定のインターフェイスの種類を表すreflect.Type値を取得するにはどうすればよいでしょうか?これは、以下に紹介するいくつかの間接的な手段を通じて達成する必要があります。

型reflect.Typeは、いくつかのメソッドを指定するインターフェース型です。これらのメソッドを通じて、reflect.Type 値によって表される Go 型に関するさまざまな情報を観察できます。これらのメソッドの中には、すべてのタイプに適用できるものもあれば、1 つまたは複数のタイプにのみ適用できるものもあります。不適切な Reflect.Type 所有者値を指定してメソッドを呼び出すと、実行時にパニックが発生します。

任意の値の型オブジェクト (reflect.Type) を取得するには、reflect.TypeOf() 関数を使用します。プログラムは、型オブジェクトを通じて任意の値の型情報にアクセスできます。例を使用して、型オブジェクトを取得するプロセスを理解しましょう。

package main

import (
    "fmt"
    "reflect"
)

func main() {

    var a int

    typeOfA := reflect.TypeOf(a)

    fmt.Println(typeOfA.Name(), typeOfA.Kind())

} 

コード出力は次のとおりです。

int  int

コードの説明は次のとおりです。

  • 10 行目では、int 型の変数を定義しています。
  • 12行目では変数aの型オブジェクトtypeOfAをreflect.TypeOf()で取得しており、型はreflect.Type()となっています。
  • 14行目では、typeOfA型オブジェクトのメンバ関数により、typeOfA変数の型名がint、種類(Kind)がintとなっています。

反射の種類(Type)と種類(Kind)を理解する

リフレクションを使用する場合は、まず Type と Kind の違いを理解する必要があります。プログラミングでは型が最もよく使われますが、反省すると多種多様な型を区別する必要がある場合には Kind が使用されます。例えば、型内のポインタを一律に判定する必要がある場合には、型(Kind)情報を利用する方が便利である。

1) 反射タイプの定義(種類)

Go プログラムの型 (Type) は、int、string、bool、float32 などのシステムのネイティブ データ型、および type キーワードで定義された型を指します。タイプ自体。たとえば、タイプ A struct{} を使用して構造体を定義する場合、A は struct{} のタイプになります。

Kind (Kind) は属するオブジェクトのタイプを指し、reflect パッケージで次のように定義されます。

type uint

const(
    Invalid Kind = iota  // 非法種類型
    Bool                // ブール型
    Int                 // 符号付き整数型
    Int8                 // 符号付き8ビット整数型
    Int16                // 符号付き16ビット整数型
    Int32                // 符号付き32ビット整数型
    Int64                // 符号付き64ビット整数型
    Unit                 // 符号なし整数型
    Uint8                // 符号なし8ビット整数型
    Uint16               // 符号なし16ビット整数型
    Uint32               // 符号なし32ビット整数型
    Uint64               // 符号なし64ビット整数型
    Uintptr              // ポインター
    Float32              // 単精度浮動小数点数
    Float64              // 倍精度浮動小数点数
    Complex64            // 64ビット複素数型
    Complex128           // 128ビット複素数型
    Array                // 配列
    Chan               // チャネル
    Func                 // 関数
    Interface            // インターフェース
    Map                 // マップ
    Ptr.                // ポインター
    Slice                // スライス
    String               // 文字列
    Struct               // 構造体
    UnsafePointer        // ローレベルポインター
) 

Map、Slice、および Chan は参照型であり、使用されるポインターに似ていますが、型定数の定義では Ptr ではなく独立した型に属します。

型 A struct{} で定義された構造体は Struct 型に属し、*A は Ptr に属します。

2) 型オブジェクトから型名と種類を取得する例

Go言語における型名に対応するリフレクション取得メソッドはreflect.TypeのName()メソッドであり、型名を表す文字列を返します。

type 属性の種類 (Kind) は、reflect.Type の Kind() メソッドを使用し、reflect.Kind 型の定数を返します。

次のコードは、定数と構造体の型情報を取得します。

package main

import (
    "fmt"
    "reflect"
)

// Enumタイプを定義
type Enum int

const (
    Zero Enum = 0
)

func main() {

    // 空の構造体を宣言する
    type cat struct {
    }

    // 構造体インスタンスの反射型オブジェクトを取得する
    typeOfCat := reflect.TypeOf(cat{})

    // 反射タイプオブジェクトの名前と種類を表示する
    fmt.Println(typeOfCat.Name(), typeOfCat.Kind())

    // Zero定数の反射型オブジェクトを取得する
    typeOfA := reflect.TypeOf(Zero)

    // 反射タイプオブジェクトの名前と種類を表示する
    fmt.Println(typeOfA.Name(), typeOfA.Kind())

} 

コード出力は次のとおりです。

cat struct
Enum int

コードの説明は次のとおりです。

  • 18 行目では、構造体タイプ cat を宣言しています。
  • 22行目でcatをインスタンス化し、reflect.TypeOf()を使ってインスタンス化されたcatのリフレクション型オブジェクトを取得します。
  • 25行目はcatの型名と型を出力していますが、型名はcat、catは構造体型に属しているので型はstructになります。
  • 28 行目で、Zero は Enum 型の定数です。 Enum 型は 9 行目で宣言され、定数は 12 行目で宣言されます。定数がなくインスタンスが作成できない場合は、reflect.TypeOf()によりリフレクション型オブジェクトを直接取得してください。
  • 31行目では、Zeroに対応する型オブジェクトの型名と型を出力します。
 

「 Go言語のreflect.TypeOf()とreflect.Type(リフレクションを通じて型情報を取得)」についてわかりやすく解説!絶対に観るべきベスト2動画

Smart Go: Intro to reflection, or data type information at runtime
ep19.1 – Go 言語の考察 – パート 1