echo.Context 的 Set() 方法是不是将值保存到底层 context.Context?
Posted
技术标签:
【中文标题】echo.Context 的 Set() 方法是不是将值保存到底层 context.Context?【英文标题】:Does Set() method of echo.Context saves the value to the underlying context.Context?echo.Context 的 Set() 方法是否将值保存到底层 context.Context? 【发布时间】:2021-11-18 09:27:46 【问题描述】:我正在使用Echo framework,并希望在设置一些自定义值后通过Go的内置context.Context
underlying echo.Context。
为了实现它,我想我可以先应用echo.Context
的Set(key string, val interface)
方法,然后提取底层的context.Context
。
问题是可以这样做吗?换句话说,echo.Context.Set(...)
是否像WithValue
一样直接在context.Context
上设置值?或者我应该采取额外的步骤来复制我的自定义条目。
附:我不想将echo.Context
传递到我的应用程序的更深层,这就是为什么我不想直接使用它而是获得引用context.Context
【问题讨论】:
【参考方案1】:方法一:重新实现 echo.Context.Get 和 echo.Context.Set 方法来操作 ctx.Request().Context() 对象。
缺点:每个Set方法都会调用一次http.Request.WithContext,复制一次*http.Request。详见WithContext方法的实现。
方法二:重新实现 echo.Context.Get 和 echo.Context.Set 方法来操作 contextValueData2 对象,并将 http.Request.WithContext 设置为自定义 context.Context contextValueData2。
缺点:在go1.13之前,context.Context需要Type断言。不要实现 context.Context 方法。与方法一相比,实现只需要一次WithContext。
建议使用方法1,清晰简单,方法2复杂,未经过充分测试。
示例导入包使用gopath,这个特性的实现也体现了echo.Context作为接口的优势。
package main
import (
"context"
"fmt"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"net/http"
)
func main()
// Echo instance
e := echo.New()
// Middleware
e.Use(NewMiddlewareContextValue)
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Routes
e.GET("/", hello)
e.GET("/val", getval)
// Start server
e.Logger.Fatal(e.Start(":1323"))
// Handler
func hello(c echo.Context) error
return c.String(http.StatusOK, "Hello, World!")
func getval(c echo.Context) error
c.Set("111", "aa")
c.Set("222", "bb")
return c.String(http.StatusOK, fmt.Sprint(c.Request().Context()))
// ---------- method1 ----------
func NewMiddlewareContextValue(fn echo.HandlerFunc) echo.HandlerFunc
return func(ctx echo.Context) error
return fn(contextValuectx)
type contextValue struct
echo.Context
// Get retrieves data from the context.
func (ctx contextValue) Get(key string) interface
// get old context value
val := ctx.Context.Get(key)
if val != nil
return val
return ctx.Request().Context().Value(key)
// Set saves data in the context.
func (ctx contextValue) Set(key string, val interface)
ctx.SetRequest(ctx.Request().WithContext(context.WithValue(ctx.Request().Context(), key, val)))
// ---------- method2 ----------
func NewMiddlewareContextValue2(fn echo.HandlerFunc) echo.HandlerFunc
return func(ctx echo.Context) error
ctxdata := contextValueData2
Context: ctx.Request().Context(),
ctx.SetRequest(ctx.Request().WithContext(ctxdata))
return fn(&contextValue2Context: ctx, contextValueData2: ctxdata)
type contextValue2 struct
echo.Context
contextValueData2
type contextValueData2 struct
context.Context
Data map[string]interface
// Get retrieves data from the context.
func (ctx *contextValue2) Get(key string) interface
// get old context value
val := ctx.Context.Get(key)
if val != nil
return val
// get my data value
val, ok := ctx.contextValueData2.Data[key]
if ok
return val
return ctx.contextValueData2.Context.Value(key)
// Set saves data in the context.
func (ctx *contextValue2) Set(key string, val interface)
if ctx.Data == nil
ctx.contextValueData2.Data = make(map[string]interface)
ctx.contextValueData2.Data[key] = val
func (ctx contextValueData2) Value(key interface) interface
str, ok := key.(string)
if ok
val, ok := ctx.Data[str]
if ok
return val
return ctx.Context.Value(key)
【讨论】:
以上是关于echo.Context 的 Set() 方法是不是将值保存到底层 context.Context?的主要内容,如果未能解决你的问题,请参考以下文章
Python set([]) 如何检查两个对象是不是相等?一个对象需要定义哪些方法来自定义它?