1

私はこれらの2つのタイプを持っています:

type Routing map[string]Handler

type Handler interface {
    Handle()
}

インターフェイスを満たす型が呼び出されMyHandler、次のようになります。

type MyHandler struct {
}

func (this *MyHandler) Handle() {
    // ...
}

私はこのようなことをしたいと思います:

// routes is created at the beginning of the program and available
// throughout the lifetime of the script

routes := Routing {
    "/route/here": MyHandler,
})

// ...

// and in another method, this line may be executed several times:

new(routes["/route/here"]).Handle()

最後の行で次のエラーが表示されます。

routes["/route/here"] はタイプではありません

その最後の行を次のように変更すると

routes["/route/here"].Handle()

それは明らかに機能します。ただし、それは Handler のインスタンスを 1 つだけ永久に使用します...そして、最後の行が実行されるたびに新しいインスタンスが必要です。Handler最後の行が実行されるたびに新しいインスタンスをインスタンス化するにはどうすればよいですか?

( を使用する場合、古いものは使用後にガベージ コレクションされると想定してnewいます。作成したインスタンスを保存していないことに注意してください。Handle()メソッドを呼び出して破棄するだけです。)

4

1 に答える 1

5

new()パラメータとして型を取り、その型のゼロ化された値へのポインタを返します。Go では、型はファースト クラスの値ではありません。New はビルトインであるため、他のコードと同じルールでは再生されません。New は、コンパイル時にどのタイプで動作するかを知る必要があります。タイプのマップを構築する方法はありません。

私の提案は、関数を使用して各タイプを構築することです。

type Routing map[string]func() Handler
routes := Routing {
    "/route/here": func() Handler { return new(MyHandler)},
}

routes["/route/here"]().Handle()

型のマップを構築する代わりに、必要な型を返す関数のマップを構築しています。


別の可能性は、上記の関数メソッドの方が好きですが、リフレクトを使用することです。このユースケースでは、リフレクトの悪用になると思います。

type Routing map[string]reflect.Type
routes := Routing {
    "/route/here": reflect.TypeOf(MyHandler{}),
}

reflect.New(routes["/route/here"]).Interface().(Handler).Handle()

警告、MyHandler が Handler を実装していない場合、プログラムがクラッシュします。このメソッドは、コンパイル時の型チェックを放棄します。

于 2013-06-14T03:19:12.197 に答える