1

I have these two types:

type Routing map[string]Handler

type Handler interface {
    Handle()
}

I have a type called MyHandler which satisfies the interface, and it looks like this:

type MyHandler struct {
}

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

I'd like to be able to do something like this:

// 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()

I get this error on the last line:

routes["/route/here"] is not a type

When I change that last line to

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

it obviously works. However, it uses just one instance of the Handler forever... and I wish for a new instance every time that last line is executed. How can I instantiate a new instance of the Handler each time that last line is executed?

(I assume that when using new, the old ones will be garbage-collected after use. Notice that I'm not saving the instance I create; I only care to call the Handle() method then have it destroyed.)

4

1 回答 1

5

new() takes a type as a parameter and returns a pointer to a zeroed out value of that type. Types are not first class values in Go. New is a builtin so it doesn't play by the same rules other code does. New needs to know at compile time what type it will be working on. There is no way to build a map of types.

My suggestion would be to use a function to build each type.

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

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

Instead of building a map of types, we are building a map of functions that return the type we want.


Another possibility is to use reflect although I like the function method above better. For this use case I believe it would be an abuse of reflect.

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

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

Warning, this will crash your program if MyHandler does not implement Handler. This method gives up compile time type checking.

于 2013-06-14T03:19:12.197 回答