英文:
How to inject an appengine.Context in martini
问题
当我尝试在中间件中注入一个appengine.Context时,出现了以下错误:
<h1>PANIC</h1>
<pre style="font-weight: bold;">找不到类型为appengine.Context的值</pre>
错误发生在以下位置:
github.com/go-martini/martini/router.go:320 (0xc3731d)
(*routeContext).run: panic(err)
github.com/go-martini/martini/router.go:221 (0xc36729)
(*route).Handle: context.run()
github.com/go-martini/martini/router.go:112 (0xc35628)
(*router).Handle: route.Handle(context, res)
app/nc_backend.go:37 (0xc30fe0)
Router.Handle.fm: m.Action(r.Handle)
go/src/pkg/runtime/asm_amd64.s:340 (0xc23b82)
go/src/pkg/reflect/value.go:474 (0xd41bd3)
go/src/pkg/reflect/value.go:345 (0xd40c65)
github.com/codegangsta/inject/inject.go:102 (0xd8449a)
(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
github.com/go-martini/martini/martini.go:165 (0xc33607)
(*context).run: _, err := c.Invoke(c.handler())
github.com/go-martini/martini/martini.go:156 (0xc33500)
(*context).Next: c.run()
github.com/go-martini/martini/recovery.go:140 (0xc37a4b)
func.004: c.Next()
go/src/pkg/runtime/asm_amd64.s:339 (0xc23b22)
go/src/pkg/reflect/value.go:474 (0xd41bd3)
go/src/pkg/reflect/value.go:345 (0xd40c65)
github.com/codegangsta/inject/inject.go:102 (0xd8449a)
(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
github.com/go-martini/martini/martini.go:165 (0xc33607)
(*context).run: _, err := c.Invoke(c.handler())
github.com/go-martini/martini/martini.go:69 (0xc32b08)
(*Martini).ServeHTTP: m.createContext(res, req).run()
go/src/pkg/net/http/server.go:1496 (0xc98dda)
go/src/pkg/appengine_internal/api_prod.go:246 (0xc26e3f)
go/src/pkg/appengine_internal/api_prod.go:212 (0xc268c5)
go/src/pkg/runtime/asm_amd64.s:340 (0xc23b82)
go/src/pkg/reflect/value.go:474 (0xd41bd3)
go/src/pkg/reflect/value.go:345 (0xd40c65)
_:410 (0xcf6255)
go/src/pkg/runtime/proc.c:279 (0xc170a0)
我做错了什么?
英文:
When I try to inject an appengine.Context from a middleware doing this:
//Share Context
m.Use(func(r *http.Request) {
    c := appengine.NewContext(r)
	c, err := appengine.Namespace(c, namespace)
	if err != nil {
		c.Debugf("[Namespace] %s", err)
	}
	m.Map(c)
})
I get this Panic saying that apparently there is no appengine.Context to be injected:
<h1>PANIC</h1>
<pre style="font-weight: bold;">Value not found for type appengine.Context</pre>
<pre>github.com/go-martini/martini/router.go:320 (0xc3731d)
	(*routeContext).run: panic(err)
github.com/go-martini/martini/router.go:221 (0xc36729)
	(*route).Handle: context.run()
github.com/go-martini/martini/router.go:112 (0xc35628)
	(*router).Handle: route.Handle(context, res)
app/nc_backend.go:37 (0xc30fe0)
	Router.Handle.fm: m.Action(r.Handle)
go/src/pkg/runtime/asm_amd64.s:340 (0xc23b82)
go/src/pkg/reflect/value.go:474 (0xd41bd3)
go/src/pkg/reflect/value.go:345 (0xd40c65)
github.com/codegangsta/inject/inject.go:102 (0xd8449a)
	(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
github.com/go-martini/martini/martini.go:165 (0xc33607)
	(*context).run: _, err := c.Invoke(c.handler())
github.com/go-martini/martini/martini.go:156 (0xc33500)
	(*context).Next: c.run()
github.com/go-martini/martini/recovery.go:140 (0xc37a4b)
	func.004: c.Next()
go/src/pkg/runtime/asm_amd64.s:339 (0xc23b22)
go/src/pkg/reflect/value.go:474 (0xd41bd3)
go/src/pkg/reflect/value.go:345 (0xd40c65)
github.com/codegangsta/inject/inject.go:102 (0xd8449a)
	(*injector).Invoke: return reflect.ValueOf(f).Call(in), nil
github.com/go-martini/martini/martini.go:165 (0xc33607)
	(*context).run: _, err := c.Invoke(c.handler())
github.com/go-martini/martini/martini.go:69 (0xc32b08)
	(*Martini).ServeHTTP: m.createContext(res, req).run()
go/src/pkg/net/http/server.go:1496 (0xc98dda)
go/src/pkg/appengine_internal/api_prod.go:246 (0xc26e3f)
go/src/pkg/appengine_internal/api_prod.go:212 (0xc268c5)
go/src/pkg/runtime/asm_amd64.s:340 (0xc23b82)
go/src/pkg/reflect/value.go:474 (0xd41bd3)
go/src/pkg/reflect/value.go:345 (0xd40c65)
_:410 (0xcf6255)
go/src/pkg/runtime/proc.c:279 (0xc170a0)
</pre>
What am I doing wrong?
答案1
得分: 3
appengine.Context 是一个接口,所以你需要使用替代方法 MapTo。根据文档,映射应该在 martini 的 Context 上执行,而不是在 Martini 对象本身上执行。
所以你的代码应该是:
m.Use(func(c martini.Context, req *http.Request) {
    ctx := appengine.NewContext(req)
    ctx, err := appengine.Namespace(ctx, namespace)
    if err != nil {
        ctx.Debugf("[Namespace] %s", err)
    }
    c.MapTo(ctx, (*appengine.Context)(nil))
})
英文:
appengine.Context is an interface, so you have to use the alternative MapTo. Also, according to the docs, mapping should be performed on the martini Context, not on the Martini object itself.
So your code should be:
m.Use(func(c martini.Context, req *http.Request) {
	ctx := appengine.NewContext(req)
    ctx, err := appengine.Namespace(ctx, namespace)
    if err != nil {
        ctx.Debugf("[Namespace] %s", err)
    }
	c.MapTo(ctx, (*appengine.Context)(nil))
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论