web-dev-qa-db-ja.com

インスタンスの新しいタイプ(Golang)

文字列からTypeの新しいインスタンスを作成する方法を教えてもらえますか?反射する?

例はありますが、それらは古い(Go 1より前のバージョン)言語用です[:(]

17
Accex

したがって、私があなたの質問を正しく理解していれば、型の名前を文字列として持っているだけでオブジェクトを作成する方法について質問していることになります。したがって、たとえば、文字列「MyStruct」があり、このタイプのオブジェクトを作成したい場合があります。

残念ながら、Goは静的に型付けされた言語であり、リンカーはデッドコード(またはそのインライン部分)を排除するため、これは簡単には不可能です。したがって、最終的な実行可能ファイルに「MyStruct」のコードが含まれるという保証はありません。

ただし、グローバル_map[string]reflect.Type_を手動で維持することはできます。たとえば、このような検出可能なタイプを定義するパッケージのinit()関数でこのマップを初期化することによって。これにより、型を使用していることもコンパイラに通知されます。その後、このマップを使用して、作成するタイプの reflect.Type を検索し、 reflect.New を使用してその新しいオブジェクトへのポインターを取得できます。タイプ(reflect.Valueとして格納されます)。次のようなインターフェイスにオブジェクトを抽出できます。

_reflect.New(yourtype).Elem().Interface()
_

Elem() はポインタを逆参照し、 Interface() は反映された値を_interface{}_として返します。詳細については、 反射の法則 を参照してください。

PS:リフレクションさえ必要とせず、コンパイラーがより多くのエラーをキャッチできるようにする、プログラムを構造化するためのより良い方法があるかもしれません。たとえば、 ファクトリメソッド の使用を検討しましたか?他の簡単な解決策は、その名前で新しいオブジェクトを作成するために呼び出すことができる関数のmap[string]func() interface{}を維持することかもしれません。

31
tux21b

事前定義されたコンストラクターを持つファクトリは、次のようなものに基づくことができます。

package main

import (
    "fmt"
)

type Creator func() interface{}

type A struct {
    a int
}

type B struct {
    a bool
}

func NewA() interface{} {
    return new(A)
}

func NewB() interface{} {
    return new(B)
}

func main() {
    m := map[string]Creator{}
    m["A"] = NewA
    m["B"] = NewB
    for k, v := range m {
        fmt.Printf("%v -> %v\n", k, v())
    }
}
6
Mirek Rusin